diff options
258 files changed, 21132 insertions, 7466 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 0ad4692c2820..6c60b4fe0ddf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4748,6 +4748,13 @@ S: Maintained F: Documentation/hwmon/k8temp F: drivers/hwmon/k8temp.c +KTAP +M: Jovi Zhangwei <[email protected]> +W: http://www.ktap.org +S: Maintained +F: drivers/staging/ktap/ + KCONFIG M: Michal Marek <[email protected]> diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 3bfdaa8d80a9..3b1501b7d894 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -150,4 +150,6 @@ source "drivers/staging/dgnc/Kconfig" source "drivers/staging/dgap/Kconfig" +source "drivers/staging/ktap/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index b0d3303b4680..2270ed077bde 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -67,3 +67,4 @@ obj-$(CONFIG_XILLYBUS) += xillybus/ obj-$(CONFIG_DGNC) += dgnc/ obj-$(CONFIG_DGAP) += dgap/ obj-$(CONFIG_MTD_SPINAND_MT29F) += mt29f_spinand/ +obj-$(CONFIG_KTAP) += ktap/ diff --git a/drivers/staging/bcm/Bcmnet.c b/drivers/staging/bcm/Bcmnet.c index 4e470d4bb4e8..a567894753aa 100644 --- a/drivers/staging/bcm/Bcmnet.c +++ b/drivers/staging/bcm/Bcmnet.c @@ -142,7 +142,8 @@ static void bcm_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(dev); - struct bcm_interface_adapter *psIntfAdapter = Adapter->pvInterfaceAdapter; + struct bcm_interface_adapter *psIntfAdapter = + Adapter->pvInterfaceAdapter; struct usb_device *udev = interface_to_usbdev(psIntfAdapter->interface); strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); diff --git a/drivers/staging/btmtk_usb/btmtk_usb.c b/drivers/staging/btmtk_usb/btmtk_usb.c index 0e783e8d71ca..7a9bf3b57810 100644 --- a/drivers/staging/btmtk_usb/btmtk_usb.c +++ b/drivers/staging/btmtk_usb/btmtk_usb.c @@ -16,7 +16,8 @@ * 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 - * or on the worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. + * or on the worldwide web at + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * */ @@ -72,8 +73,9 @@ static int btmtk_usb_reset(struct usb_device *udev) BT_DBG("%s\n", __func__); - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01, DEVICE_VENDOR_REQUEST_OUT, - 0x01, 0x00, NULL, 0x00, CONTROL_TIMEOUT_JIFFIES); + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01, + DEVICE_VENDOR_REQUEST_OUT, 0x01, 0x00, + NULL, 0x00, CONTROL_TIMEOUT_JIFFIES); if (ret < 0) { BT_ERR("%s error(%d)\n", __func__, ret); @@ -91,20 +93,22 @@ static int btmtk_usb_io_read32(struct btmtk_usb_data *data, u32 reg, u32 *val) u8 request = data->r_request; struct usb_device *udev = data->udev; int ret; + __le32 val_le; - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), request, DEVICE_VENDOR_REQUEST_IN, - 0x0, reg, data->io_buf, 4, - CONTROL_TIMEOUT_JIFFIES); + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), request, + DEVICE_VENDOR_REQUEST_IN, 0x0, reg, data->io_buf, + 4, CONTROL_TIMEOUT_JIFFIES); if (ret < 0) { *val = 0xffffffff; - BT_ERR("%s error(%d), reg=%x, value=%x\n", __func__, ret, reg, *val); + BT_ERR("%s error(%d), reg=%x, value=%x\n", + __func__, ret, reg, *val); return ret; } - memmove(val, data->io_buf, 4); + memmove(&val_le, data->io_buf, 4); - *val = le32_to_cpu(*val); + *val = le32_to_cpu(val_le); if (ret > 0) ret = 0; @@ -122,12 +126,13 @@ static int btmtk_usb_io_write32(struct btmtk_usb_data *data, u32 reg, u32 val) index = (u16)reg; value = val & 0x0000ffff; - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request, DEVICE_VENDOR_REQUEST_OUT, - value, index, NULL, 0, - CONTROL_TIMEOUT_JIFFIES); + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request, + DEVICE_VENDOR_REQUEST_OUT, value, index, + NULL, 0, CONTROL_TIMEOUT_JIFFIES); if (ret < 0) { - BT_ERR("%s error(%d), reg=%x, value=%x\n", __func__, ret, reg, val); + BT_ERR("%s error(%d), reg=%x, value=%x\n", + __func__, ret, reg, val); return ret; } @@ -139,7 +144,8 @@ static int btmtk_usb_io_write32(struct btmtk_usb_data *data, u32 reg, u32 val) value, index, NULL, 0, CONTROL_TIMEOUT_JIFFIES); if (ret < 0) { - BT_ERR("%s error(%d), reg=%x, value=%x\n", __func__, ret, reg, val); + BT_ERR("%s error(%d), reg=%x, value=%x\n", + __func__, ret, reg, val); return ret; } @@ -186,13 +192,15 @@ static void btmtk_usb_cap_init(struct btmtk_usb_data *data) ret = request_firmware(&firmware, MT7650_FIRMWARE, &udev->dev); if (ret < 0) { if (ret == -ENOENT) { - BT_ERR("Firmware file \"%s\" not found \n", MT7650_FIRMWARE); + BT_ERR("Firmware file \"%s\" not found\n", + MT7650_FIRMWARE); } else { - BT_ERR("Firmware file \"%s\" request failed (err=%d) \n", + BT_ERR("Firmware file \"%s\" request failed (err=%d)\n", MT7650_FIRMWARE, ret); } } else { - BT_DBG("Firmware file \"%s\" Found \n", MT7650_FIRMWARE); + BT_DBG("Firmware file \"%s\" Found\n", + MT7650_FIRMWARE); /* load firmware here */ data->firmware = firmware; btmtk_usb_load_fw(data); @@ -205,7 +213,8 @@ static void btmtk_usb_cap_init(struct btmtk_usb_data *data) ret = request_firmware(&firmware, MT7662_FIRMWARE, &udev->dev); if (ret < 0) { if (ret == -ENOENT) { - BT_ERR("Firmware file \"%s\" not found\n", MT7662_FIRMWARE); + BT_ERR("Firmware file \"%s\" not found\n", + MT7662_FIRMWARE); } else { BT_ERR("Firmware file \"%s\" request failed (err=%d)\n", MT7662_FIRMWARE, ret); @@ -241,9 +250,8 @@ static u16 checksume16(u8 *pData, int len) if (len) sum += *((u8 *)pData); - while (sum >> 16) { + while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); - } return ~sum; } @@ -258,13 +266,12 @@ static int btmtk_usb_chk_crc(struct btmtk_usb_data *data, u32 checksum_len) memmove(data->io_buf, &data->rom_patch_offset, 4); memmove(&data->io_buf[4], &checksum_len, 4); - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x1, DEVICE_VENDOR_REQUEST_IN, - 0x20, 0x00, data->io_buf, 8, - CONTROL_TIMEOUT_JIFFIES); + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x1, + DEVICE_VENDOR_REQUEST_IN, 0x20, 0x00, data->io_buf, + 8, CONTROL_TIMEOUT_JIFFIES); - if (ret < 0) { + if (ret < 0) BT_ERR("%s error(%d)\n", __func__, ret); - } return ret; } @@ -274,6 +281,7 @@ static u16 btmtk_usb_get_crc(struct btmtk_usb_data *data) int ret = 0; struct usb_device *udev = data->udev; u16 crc, count = 0; + __le16 crc_le; BT_DBG("%s\n", __func__); @@ -288,9 +296,9 @@ static u16 btmtk_usb_get_crc(struct btmtk_usb_data *data) BT_ERR("%s error(%d)\n", __func__, ret); } - memmove(&crc, data->io_buf, 2); + memmove(&crc_le, data->io_buf, 2); - crc = le16_to_cpu(crc); + crc = le16_to_cpu(crc_le); if (crc != 0xFFFF) break; @@ -318,8 +326,8 @@ static int btmtk_usb_reset_wmt(struct btmtk_usb_data *data) BT_DBG("%s\n", __func__); ret = usb_control_msg(data->udev, usb_sndctrlpipe(data->udev, 0), 0x01, - DEVICE_CLASS_REQUEST_OUT, 0x12, 0x00, data->io_buf, - 8, CONTROL_TIMEOUT_JIFFIES); + DEVICE_CLASS_REQUEST_OUT, 0x12, 0x00, + data->io_buf, 8, CONTROL_TIMEOUT_JIFFIES); if (ret) BT_ERR("%s:(%d)\n", __func__, ret); @@ -350,7 +358,8 @@ static int btmtk_usb_load_rom_patch(struct btmtk_usb_data *data) unsigned char phase; void *buf; char *pos; - unsigned int pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress); + unsigned int pipe; + pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress); if (!data->firmware) { BT_ERR("%s:please assign a rom patch\n", __func__); @@ -391,7 +400,8 @@ load_patch_protect: goto error0; } - buf = usb_alloc_coherent(data->udev, UPLOAD_PATCH_UNIT, GFP_ATOMIC, &data_dma); + buf = usb_alloc_coherent(data->udev, UPLOAD_PATCH_UNIT, + GFP_ATOMIC, &data_dma); if (!buf) { ret = -ENOMEM; @@ -409,78 +419,82 @@ load_patch_protect: /* loading rom patch */ while (1) { s32 sent_len_max = UPLOAD_PATCH_UNIT - PATCH_HEADER_SIZE; - sent_len = (patch_len - cur_len) >= sent_len_max ? sent_len_max : (patch_len - cur_len); + sent_len = min_t(s32, (patch_len - cur_len), sent_len_max); BT_DBG("patch_len = %d\n", patch_len); BT_DBG("cur_len = %d\n", cur_len); BT_DBG("sent_len = %d\n", sent_len); - if (sent_len > 0) { - if (first_block == 1) { - if (sent_len < sent_len_max) - phase = PATCH_PHASE3; - else - phase = PATCH_PHASE1; - first_block = 0; - } else if (sent_len == sent_len_max) { - phase = PATCH_PHASE2; - } else { + if (sent_len <= 0) + break; + + if (first_block == 1) { + if (sent_len < sent_len_max) phase = PATCH_PHASE3; - } + else + phase = PATCH_PHASE1; + first_block = 0; + } else if (sent_len == sent_len_max) { + phase = PATCH_PHASE2; + } else { + phase = PATCH_PHASE3; + } - /* prepare HCI header */ - pos[0] = 0x6F; - pos[1] = 0xFC; - pos[2] = (sent_len + 5) & 0xFF; - pos[3] = ((sent_len + 5) >> 8) & 0xFF; + /* prepare HCI header */ + pos[0] = 0x6F; + pos[1] = 0xFC; + pos[2] = (sent_len + 5) & 0xFF; + pos[3] = ((sent_len + 5) >> 8) & 0xFF; - /* prepare WMT header */ - pos[4] = 0x01; - pos[5] = 0x01; - pos[6] = (sent_len + 1) & 0xFF; - pos[7] = ((sent_len + 1) >> 8) & 0xFF; + /* prepare WMT header */ + pos[4] = 0x01; + pos[5] = 0x01; + pos[6] = (sent_len + 1) & 0xFF; + pos[7] = ((sent_len + 1) >> 8) & 0xFF; - pos[8] = phase; + pos[8] = phase; - memcpy(&pos[9], data->firmware->data + PATCH_INFO_SIZE + cur_len, sent_len); + memcpy(&pos[9], + data->firmware->data + PATCH_INFO_SIZE + cur_len, + sent_len); - BT_DBG("sent_len + PATCH_HEADER_SIZE = %d, phase = %d\n", - sent_len + PATCH_HEADER_SIZE, phase); + BT_DBG("sent_len + PATCH_HEADER_SIZE = %d, phase = %d\n", + sent_len + PATCH_HEADER_SIZE, phase); - usb_fill_bulk_urb(urb, - data->udev, - pipe, - buf, - sent_len + PATCH_HEADER_SIZE, - load_rom_patch_complete, - &sent_to_mcu_done); + usb_fill_bulk_urb(urb, + data->udev, + pipe, + buf, + sent_len + PATCH_HEADER_SIZE, + load_rom_patch_complete, + &sent_to_mcu_done); - urb->transfer_dma = data_dma; - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + urb->transfer_dma = data_dma; + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - ret = usb_submit_urb(urb, GFP_ATOMIC); + ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) - goto error2; + if (ret) + goto error2; - if (!wait_for_completion_timeout(&sent_to_mcu_done, msecs_to_jiffies(1000))) { - usb_kill_urb(urb); - BT_ERR("upload rom_patch timeout\n"); - goto error2; - } + if (!wait_for_completion_timeout(&sent_to_mcu_done, + msecs_to_jiffies(1000))) { + usb_kill_urb(urb); + BT_ERR("upload rom_patch timeout\n"); + goto error2; + } - BT_DBG("."); + BT_DBG("."); - mdelay(200); + mdelay(200); - cur_len += sent_len; + cur_len += sent_len; - } else { - break; - } } - total_checksum = checksume16((u8 *)data->firmware->data + PATCH_INFO_SIZE, patch_len); + total_checksum = checksume16( + (u8 *)data->firmware->data + PATCH_INFO_SIZE, + patch_len); BT_DBG("Send checksum req..\n"); @@ -520,8 +534,8 @@ static int load_fw_iv(struct btmtk_usb_data *data) memmove(buf, data->firmware->data + 32, 64); ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01, - DEVICE_VENDOR_REQUEST_OUT, 0x12, 0x0, buf, 64, - CONTROL_TIMEOUT_JIFFIES); + DEVICE_VENDOR_REQUEST_OUT, 0x12, 0x0, buf, 64, + CONTROL_TIMEOUT_JIFFIES); if (ret < 0) { BT_ERR("%s error(%d) step4\n", __func__, ret); @@ -552,6 +566,7 @@ static int btmtk_usb_load_fw(struct btmtk_usb_data *data) void *buf; u32 cur_len = 0; u32 packet_header = 0; + __le32 packet_header_le; u32 value; u32 ilm_len = 0, dlm_len = 0; u16 fw_ver, build_ver; @@ -559,7 +574,8 @@ static int btmtk_usb_load_fw(struct btmtk_usb_data *data) dma_addr_t data_dma; int ret = 0, sent_len; struct completion sent_to_mcu_done; - unsigned int pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress); + unsigned int pipe; + pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress); if (!data->firmware) { BT_ERR("%s:please assign a fw\n", __func__); @@ -598,9 +614,11 @@ loadfw_protect: | (*(data->firmware->data + 5) << 8) | (*(data->firmware->data + 4)); - fw_ver = (*(data->firmware->data + 11) << 8) | (*(data->firmware->data + 10)); + fw_ver = (*(data->firmware->data + 11) << 8) | + (*(data->firmware->data + 10)); - build_ver = (*(data->firmware->data + 9) << 8) | (*(data->firmware->data + 8)); + build_ver = (*(data->firmware->data + 9) << 8) | + (*(data->firmware->data + 8)); BT_DBG("fw version:%d.%d.%02d ", (fw_ver & 0xf000) >> 8, @@ -657,22 +675,22 @@ loadfw_protect: /* Loading ILM */ while (1) { - sent_len = (ilm_len - cur_len) >= 14336 ? 14336 : (ilm_len - cur_len); + sent_len = min_t(s32, (ilm_len - cur_len), 14336); if (sent_len > 0) { packet_header &= ~(0xffffffff); packet_header |= (sent_len << 16); - packet_header = cpu_to_le32(packet_header); + packet_header_le = cpu_to_le32(packet_header); - memmove(buf, &packet_header, 4); - memmove(buf + 4, data->firmware->data + 32 + cur_len, sent_len); + memmove(buf, &packet_header_le, 4); + memmove(buf + 4, data->firmware->data + 32 + cur_len, + sent_len); /* U2M_PDMA descriptor */ btmtk_usb_io_write32(data, 0x230, cur_len); - while ((sent_len % 4) != 0) { + while ((sent_len % 4) != 0) sent_len++; - } /* U2M_PDMA length */ btmtk_usb_io_write32(data, 0x234, sent_len << 16); @@ -693,7 +711,8 @@ loadfw_protect: if (ret) goto error3; - if (!wait_for_completion_timeout(&sent_to_mcu_done, msecs_to_jiffies(1000))) { + if (!wait_for_completion_timeout(&sent_to_mcu_done, + msecs_to_jiffies(1000))) { usb_kill_urb(urb); BT_ERR("upload ilm fw timeout\n"); goto error3; @@ -714,58 +733,60 @@ loadfw_protect: /* Loading DLM */ while (1) { - sent_len = (dlm_len - cur_len) >= 14336 ? 14336 : (dlm_len - cur_len); + sent_len = min_t(s32, (dlm_len - cur_len), 14336); - if (sent_len > 0) { - packet_header &= ~(0xffffffff); - packet_header |= (sent_len << 16); - packet_header = cpu_to_le32(packet_header); + if (sent_len <= 0) + break; - memmove(buf, &packet_header, 4); - memmove(buf + 4, data->firmware->data + 32 + ilm_len + cur_len, sent_len); + packet_header &= ~(0xffffffff); + packet_header |= (sent_len << 16); + packet_header_le = cpu_to_le32(packet_header); - /* U2M_PDMA descriptor */ - btmtk_usb_io_write32(data, 0x230, 0x80000 + cur_len); + memmove(buf, &packet_header_le, 4); + memmove(buf + 4, + data->firmware->data + 32 + ilm_len + cur_len, + sent_len); - while ((sent_len % 4) != 0) { - BT_DBG("sent_len is not divided by 4\n"); - sent_len++; - } + /* U2M_PDMA descriptor */ + btmtk_usb_io_write32(data, 0x230, 0x80000 + cur_len); - /* U2M_PDMA length */ - btmtk_usb_io_write32(data, 0x234, sent_len << 16); + while ((sent_len % 4) != 0) { + BT_DBG("sent_len is not divided by 4\n"); + sent_len++; + } - usb_fill_bulk_urb(urb, - udev, - pipe, - buf, - sent_len + 4, - load_fw_complete, - &sent_to_mcu_done); + /* U2M_PDMA length */ + btmtk_usb_io_write32(data, 0x234, sent_len << 16); - urb->transfer_dma = data_dma; - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + usb_fill_bulk_urb(urb, + udev, + pipe, + buf, + sent_len + 4, + load_fw_complete, + &sent_to_mcu_done); - ret = usb_submit_urb(urb, GFP_ATOMIC); + urb->transfer_dma = data_dma; + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - if (ret) - goto error3; + ret = usb_submit_urb(urb, GFP_ATOMIC); - if (!wait_for_completion_timeout(&sent_to_mcu_done, msecs_to_jiffies(1000))) { - usb_kill_urb(urb); - BT_ERR("upload dlm fw timeout\n"); - goto error3; - } + if (ret) + goto error3; - BT_DBG("."); + if (!wait_for_completion_timeout(&sent_to_mcu_done, + msecs_to_jiffies(1000))) { + usb_kill_urb(urb); + BT_ERR("upload dlm fw timeout\n"); + goto error3; + } - mdelay(500); + BT_DBG("."); - cur_len += sent_len; + mdelay(500); + + cur_len += sent_len; - } else { - break; - } } /* upload 64bytes interrupt vector */ @@ -921,9 +942,8 @@ static void btmtk_usb_bulk_in_complete(struct urb *urb) BT_DBG("%s:%s urb %p status %d count %d", __func__, hdev->name, urb, urb->status, urb->actual_length); - if (!test_bit(HCI_RUNNING, &hdev->flags)) { + if (!test_bit(HCI_RUNNING, &hdev->flags)) return; - } if (urb->status == 0) { hdev->stat.byte_rx += urb->actual_length; @@ -978,8 +998,8 @@ static int btmtk_usb_submit_bulk_in_urb(struct hci_dev *hdev, gfp_t mem_flags) pipe = usb_rcvbulkpipe(data->udev, data->bulk_rx_ep->bEndpointAddress); - usb_fill_bulk_urb(urb, data->udev, pipe, - buf, size, btmtk_usb_bulk_in_complete, hdev); + usb_fill_bulk_urb(urb, data->udev, pipe, buf, size, + btmtk_usb_bulk_in_complete, hdev); urb->transfer_flags |= URB_FREE_BUFFER; @@ -1015,7 +1035,8 @@ static void btmtk_usb_isoc_in_complete(struct urb *urb) if (urb->status == 0) { for (i = 0; i < urb->number_of_packets; i++) { unsigned int offset = urb->iso_frame_desc[i].offset; - unsigned int length = urb->iso_frame_desc[i].actual_length; + unsigned int length; + length = urb->iso_frame_desc[i].actual_length; if (urb->iso_frame_desc[i].status) continue; @@ -1096,8 +1117,9 @@ static int btmtk_usb_submit_isoc_in_urb(struct hci_dev *hdev, gfp_t mem_flags) pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress); - usb_fill_int_urb(urb, data->udev, pipe, buf, size, btmtk_usb_isoc_in_complete, - hdev, data->isoc_rx_ep->bInterval); + usb_fill_int_urb(urb, data->udev, pipe, buf, size, + btmtk_usb_isoc_in_complete, hdev, + data->isoc_rx_ep->bInterval); urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP; @@ -1306,7 +1328,8 @@ static int btmtk_usb_send_frame(struct sk_buff *skb) } usb_fill_control_urb(urb, data->udev, pipe, (void *) dr, - skb->data, skb->len, btmtk_usb_tx_complete, skb); + skb->data, skb->len, + btmtk_usb_tx_complete, skb); hdev->stat.cmd_tx++; break; @@ -1322,8 +1345,8 @@ static int btmtk_usb_send_frame(struct sk_buff *skb) pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress); - usb_fill_bulk_urb(urb, data->udev, pipe, - skb->data, skb->len, btmtk_usb_tx_complete, skb); + usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, + skb->len, btmtk_usb_tx_complete, skb); hdev->stat.acl_tx++; BT_DBG("HCI_ACLDATA_PKT:\n"); @@ -1442,7 +1465,8 @@ static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting) static void btmtk_usb_work(struct work_struct *work) { - struct btmtk_usb_data *data = container_of(work, struct btmtk_usb_data, work); + struct btmtk_usb_data *data = container_of(work, struct btmtk_usb_data, + work); struct hci_dev *hdev = data->hdev; int new_alts; int err; @@ -1451,7 +1475,8 @@ static void btmtk_usb_work(struct work_struct *work) if (hdev->conn_hash.sco_num > 0) { if (!test_bit(BTUSB_DID_ISO_RESUME, &data->flags)) { - err = usb_autopm_get_interface(data->isoc ? data->isoc : data->intf); + err = usb_autopm_get_interface(data->isoc ? + data->isoc : data->intf); if (err < 0) { clear_bit(BTUSB_ISOC_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->isoc_anchor); @@ -1489,13 +1514,15 @@ static void btmtk_usb_work(struct work_struct *work) __set_isoc_interface(hdev, 0); if (test_and_clear_bit(BTUSB_DID_ISO_RESUME, &data->flags)) - usb_autopm_put_interface(data->isoc ? data->isoc : data->intf); + usb_autopm_put_interface(data->isoc ? + data->isoc : data->intf); } } static void btmtk_usb_waker(struct work_struct *work) { - struct btmtk_usb_data *data = container_of(work, struct btmtk_usb_data, waker); + struct btmtk_usb_data *data = container_of(work, struct btmtk_usb_data, + waker); int err; err = usb_autopm_get_interface(data->intf); diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index 94b2385fb0af..4e26bd7fc84f 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -344,7 +344,7 @@ unsigned int comedi_buf_read_free(struct comedi_async *async, } EXPORT_SYMBOL_GPL(comedi_buf_read_free); -int comedi_buf_put(struct comedi_async *async, short x) +int comedi_buf_put(struct comedi_async *async, unsigned short x) { unsigned int n = __comedi_buf_write_alloc(async, sizeof(short), 1); @@ -352,20 +352,20 @@ int comedi_buf_put(struct comedi_async *async, short x) async->events |= COMEDI_CB_ERROR; return 0; } - *(short *)(async->prealloc_buf + async->buf_write_ptr) = x; + *(unsigned short *)(async->prealloc_buf + async->buf_write_ptr) = x; comedi_buf_write_free(async, sizeof(short)); return 1; } EXPORT_SYMBOL_GPL(comedi_buf_put); -int comedi_buf_get(struct comedi_async *async, short *x) +int comedi_buf_get(struct comedi_async *async, unsigned short *x) { unsigned int n = comedi_buf_read_n_available(async); if (n < sizeof(short)) return 0; comedi_buf_read_alloc(async, sizeof(short)); - *x = *(short *)(async->prealloc_buf + async->buf_read_ptr); + *x = *(unsigned short *)(async->prealloc_buf + async->buf_read_ptr); comedi_buf_read_free(async, sizeof(short)); return 1; } diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 1636c7ca57e2..721df313f8df 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -543,7 +543,7 @@ void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size) { s->private = kzalloc(size, GFP_KERNEL); if (s->private) - comedi_set_subdevice_runflags(s, ~0, SRF_FREE_SPRIV); + s->runflags |= SRF_FREE_SPRIV; return s->private; } EXPORT_SYMBOL_GPL(comedi_alloc_spriv); @@ -806,7 +806,6 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, } else { us->range_type = 0; /* XXX */ } - us->flags = s->flags; if (s->busy) us->subd_flags |= SDF_BUSY; @@ -818,8 +817,6 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, us->subd_flags |= SDF_LOCK_OWNER; if (!s->maxdata && s->maxdata_list) us->subd_flags |= SDF_MAXDATA; - if (s->flaglist) - us->subd_flags |= SDF_FLAGS; if (s->range_table_list) us->subd_flags |= SDF_RANGETYPE; if (s->do_cmd) @@ -829,8 +826,6 @@ static int do_subdinfo_ioctl(struct comedi_device *dev, us->insn_bits_support = COMEDI_SUPPORTED; else us->insn_bits_support = COMEDI_UNSUPPORTED; - - us->settling_time_0 = s->settling_time_0; } ret = copy_to_user(arg, tmp, dev->n_subdevices * sizeof(*tmp)); @@ -875,13 +870,8 @@ static int do_chaninfo_ioctl(struct comedi_device *dev, return -EFAULT; } - if (it.flaglist) { - if (!s->flaglist) - return -EINVAL; - if (copy_to_user(it.flaglist, s->flaglist, - s->n_chan * sizeof(unsigned int))) - return -EFAULT; - } + if (it.flaglist) + return -EINVAL; /* flaglist not supported */ if (it.rangelist) { int i; @@ -1485,7 +1475,8 @@ static int do_cmd_ioctl(struct comedi_device *dev, if (async->cmd.flags & TRIG_WAKE_EOS) async->cb_mask |= COMEDI_CB_EOS; - comedi_set_subdevice_runflags(s, ~0, SRF_USER | SRF_RUNNING); + comedi_set_subdevice_runflags(s, SRF_USER | SRF_ERROR | SRF_RUNNING, + SRF_USER | SRF_RUNNING); /* set s->busy _after_ setting SRF_RUNNING flag to avoid race with * comedi_read() or comedi_write() */ diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 6db099bdbc58..143be8076a2e 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -57,11 +57,6 @@ struct comedi_subdevice { 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 struct comedi_lrange *range_table; const struct comedi_lrange *const *range_table_list; @@ -351,8 +346,8 @@ unsigned int comedi_buf_read_n_available(struct comedi_async *); unsigned int comedi_buf_read_alloc(struct comedi_async *, unsigned int); unsigned int comedi_buf_read_free(struct comedi_async *, unsigned int); -int comedi_buf_put(struct comedi_async *, short); -int comedi_buf_get(struct comedi_async *, short *); +int comedi_buf_put(struct comedi_async *, unsigned short); +int comedi_buf_get(struct comedi_async *, unsigned short *); void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset, const void *source, unsigned int num_bytes); diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c index 5737bb4c29ab..b4009e863414 100644 --- a/drivers/staging/comedi/drivers/8255.c +++ b/drivers/staging/comedi/drivers/8255.c @@ -112,7 +112,7 @@ void subdev_8255_interrupt(struct comedi_device *dev, { struct subdev_8255_private *spriv = s->private; unsigned long iobase = spriv->iobase; - short d; + unsigned short d; d = spriv->io(0, _8255_DATA, 0, iobase); d |= (spriv->io(0, _8255_DATA + 1, 0, iobase) << 8); diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h index dfd1e666cc18..2ed2da3499f4 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_common.h +++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h @@ -133,7 +133,7 @@ struct addi_private { unsigned short us_UseDma; /* To use Dma or not */ unsigned char b_DmaDoubleBuffer; /* we can use double buffering */ unsigned int ui_DmaActualBuffer; /* which buffer is used now */ - short *ul_DmaBufferVirtual[2]; /* pointers to begin of DMA buffer */ + unsigned short *ul_DmaBufferVirtual[2]; /* pointers to DMA buffer */ unsigned int ul_DmaBufferHw[2]; /* hw address of DMA buff */ unsigned int ui_DmaBufferSize[2]; /* size of dma buffer in bytes */ unsigned int ui_DmaBufferUsesize[2]; /* which size we may now used for transfer */ diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c index ac6e75d62e61..3c9eec84f0eb 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c @@ -1391,7 +1391,7 @@ static int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, */ static void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev, struct comedi_subdevice *s, - short *dma_buffer, + unsigned short *dma_buffer, unsigned int num_samples) { struct addi_private *devpriv = dev->private; diff --git a/drivers/staging/comedi/drivers/adl_pci9111.c b/drivers/staging/comedi/drivers/adl_pci9111.c index 4db46f0f315e..eab8da2c3d66 100644 --- a/drivers/staging/comedi/drivers/adl_pci9111.c +++ b/drivers/staging/comedi/drivers/adl_pci9111.c @@ -151,7 +151,7 @@ struct pci9111_private_data { unsigned int div1; unsigned int div2; - short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE]; + unsigned short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE]; }; static void plx9050_interrupt_control(unsigned long io_base, @@ -567,7 +567,7 @@ static void pci9111_ai_munge(struct comedi_device *dev, unsigned int num_bytes, unsigned int start_chan_index) { - short *array = data; + unsigned short *array = data; unsigned int maxdata = s->maxdata; unsigned int invert = (maxdata + 1) >> 1; unsigned int shift = (maxdata == 0xffff) ? 0 : 4; diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index bd5c8bbad090..0f2e8591c697 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -352,12 +352,11 @@ struct pci9118_private { * on external start */ unsigned int ai_data_len; - short *ai_data; - short ao_data[2]; /* data output buffer */ + unsigned short ao_data[2]; /* data output buffer */ unsigned int ai_scans; /* number of scans to do */ char dma_doublebuf; /* we can use double buffering */ unsigned int dma_actbuf; /* which buffer is used now */ - short *dmabuf_virt[2]; /* + unsigned short *dmabuf_virt[2]; /* * pointers to begin of * DMA buffer */ @@ -700,7 +699,7 @@ static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev) static unsigned int defragment_dma_buffer(struct comedi_device *dev, struct comedi_subdevice *s, - short *dma_buffer, + unsigned short *dma_buffer, unsigned int num_samples) { struct pci9118_private *devpriv = dev->private; @@ -724,7 +723,7 @@ static unsigned int defragment_dma_buffer(struct comedi_device *dev, static int move_block_from_dma(struct comedi_device *dev, struct comedi_subdevice *s, - short *dma_buffer, + unsigned short *dma_buffer, unsigned int num_samples) { struct pci9118_private *devpriv = dev->private; @@ -925,7 +924,7 @@ static void pci9118_ai_munge(struct comedi_device *dev, { struct pci9118_private *devpriv = dev->private; unsigned int i, num_samples = num_bytes / sizeof(short); - short *array = data; + unsigned short *array = data; for (i = 0; i < num_samples; i++) { if (devpriv->usedma) @@ -945,7 +944,7 @@ static void interrupt_pci9118_ai_onesample(struct comedi_device *dev, unsigned short int_daq) { struct pci9118_private *devpriv = dev->private; - register short sampl; + unsigned short sampl; s->async->events = 0; @@ -1613,7 +1612,6 @@ static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 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; @@ -1987,8 +1985,8 @@ static int pci9118_common_attach(struct comedi_device *dev, int disable_irq, for (i = 0; i < 2; i++) { for (pages = 4; pages >= 0; pages--) { devpriv->dmabuf_virt[i] = - (short *)__get_free_pages(GFP_KERNEL, - pages); + (unsigned short *) + __get_free_pages(GFP_KERNEL, pages); if (devpriv->dmabuf_virt[i]) break; } diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 49b39ec22708..c3fdcabe9aec 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -314,10 +314,9 @@ struct pci1710_private { 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 short ao_data[4]; /* data output buffer */ unsigned int cnt0_write_wait; /* after a write, wait for update of the * internal state */ }; @@ -736,7 +735,7 @@ static void interrupt_pci1710_every_sample(void *d) int m; #ifdef PCI171x_PARANOIDCHECK const struct boardtype *this_board = comedi_board(dev); - short sampl; + unsigned short sampl; #endif m = inw(dev->iobase + PCI171x_STATUS); @@ -817,7 +816,7 @@ static int move_block_from_fifo(struct comedi_device *dev, int i, j; #ifdef PCI171x_PARANOIDCHECK const struct boardtype *this_board = comedi_board(dev); - int sampl; + unsigned short sampl; #endif j = s->async->cur_chan; @@ -1122,7 +1121,6 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 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; diff --git a/drivers/staging/comedi/drivers/adv_pci1723.c b/drivers/staging/comedi/drivers/adv_pci1723.c index 71321f75d0cd..bd4f781b4b24 100644 --- a/drivers/staging/comedi/drivers/adv_pci1723.c +++ b/drivers/staging/comedi/drivers/adv_pci1723.c @@ -105,7 +105,7 @@ TODO: struct pci1723_private { unsigned char da_range[8]; /* D/A output range for each channel */ - short ao_data[8]; /* data output buffer */ + unsigned short ao_data[8]; /* data output buffer */ }; /* diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index cf385b8e32bf..810e397d8fd7 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -373,7 +373,7 @@ struct pci224_private { unsigned long state; spinlock_t ao_spinlock; unsigned int *ao_readback; - short *ao_scan_vals; + unsigned short *ao_scan_vals; unsigned char *ao_scan_order; int intr_cpuid; short intr_running; @@ -1112,7 +1112,7 @@ pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, const struct pci224_board *thisboard = comedi_board(dev); struct pci224_private *devpriv = dev->private; struct comedi_async *async = s->async; - short *array = data; + unsigned short *array = data; unsigned int length = num_bytes / sizeof(*array); unsigned int offset; unsigned int shift; diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 43059c25d5ea..a97bbd6ca3db 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -573,14 +573,14 @@ static const struct comedi_lrange pci230_ao_range = { 2, { /* PCI230 daccon bipolar flag for each analogue output range. */ static const unsigned char pci230_ao_bipolar[2] = { 0, 1 }; -static short pci230_ai_read(struct comedi_device *dev) +static unsigned short pci230_ai_read(struct comedi_device *dev) { const struct pci230_board *thisboard = comedi_board(dev); struct pci230_private *devpriv = dev->private; - short data; + unsigned short data; /* Read sample. */ - data = (short)inw(dev->iobase + PCI230_ADCDATA); + data = 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. */ @@ -595,7 +595,7 @@ static short pci230_ai_read(struct comedi_device *dev) } static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev, - short datum) + unsigned short datum) { const struct pci230_board *thisboard = comedi_board(dev); struct pci230_private *devpriv = dev->private; @@ -609,11 +609,12 @@ static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev, * four bits reserved for expansion). */ /* PCI230+ is also 12 bit AO. */ datum <<= (16 - thisboard->ao_bits); - return (unsigned short)datum; + return datum; } static inline void pci230_ao_write_nofifo(struct comedi_device *dev, - short datum, unsigned int chan) + unsigned short datum, + unsigned int chan) { struct pci230_private *devpriv = dev->private; @@ -627,8 +628,8 @@ static inline void pci230_ao_write_nofifo(struct comedi_device *dev, PCI230_DACOUT2)); } -static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum, - unsigned int chan) +static inline void pci230_ao_write_fifo(struct comedi_device *dev, + unsigned short datum, unsigned int chan) { struct pci230_private *devpriv = dev->private; @@ -1165,7 +1166,7 @@ static void pci230_handle_ao_nofifo(struct comedi_device *dev, struct comedi_subdevice *s) { struct pci230_private *devpriv = dev->private; - short data; + unsigned short data; int i, ret; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; @@ -1258,7 +1259,7 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev, /* Process scans. */ for (n = 0; n < num_scans; n++) { for (i = 0; i < cmd->chanlist_len; i++) { - short datum; + unsigned short datum; comedi_buf_get(async, &datum); pci230_ao_write_fifo(dev, datum, diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 0891659f9eb5..e72a403db17c 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -357,15 +357,15 @@ struct cb_pcidas_private { unsigned int s5933_intcsr_bits; unsigned int ao_control_bits; /* fifo buffers */ - short ai_buffer[AI_BUFFER_SIZE]; - short ao_buffer[AO_BUFFER_SIZE]; + unsigned short ai_buffer[AI_BUFFER_SIZE]; + unsigned short ao_buffer[AO_BUFFER_SIZE]; /* divisors of master clock for analog output pacing */ unsigned int ao_divisor1; unsigned int ao_divisor2; /* number of analog output samples remaining */ unsigned int ao_count; /* cached values for readback */ - int ao_value[2]; + unsigned short ao_value[2]; unsigned int caldac_value[NUM_CHANNELS_8800]; unsigned int trimpot_value[NUM_CHANNELS_8402]; unsigned int dac08_value; diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index e49743aed65d..ff5206536be3 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -1137,7 +1137,7 @@ struct pcidas64_private { volatile short ai_cmd_running; unsigned int ai_fifo_segment_length; struct ext_clock_info ext_clock; - short ao_bounce_buffer[DAC_FIFO_SIZE]; + unsigned short ao_bounce_buffer[DAC_FIFO_SIZE]; }; static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, diff --git a/drivers/staging/comedi/drivers/comedi_fc.h b/drivers/staging/comedi/drivers/comedi_fc.h index a4dea7cb86be..8558b07f8df3 100644 --- a/drivers/staging/comedi/drivers/comedi_fc.h +++ b/drivers/staging/comedi/drivers/comedi_fc.h @@ -30,7 +30,7 @@ extern unsigned int cfc_write_array_to_buffer(struct comedi_subdevice *subd, unsigned int num_bytes); static inline unsigned int cfc_write_to_buffer(struct comedi_subdevice *subd, - short data) + unsigned short data) { return cfc_write_array_to_buffer(subd, &data, sizeof(data)); }; diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 30f3995d7297..a8446ca04110 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -846,7 +846,7 @@ static void das16_ai_munge(struct comedi_device *dev, unsigned int start_chan_index) { unsigned int i, num_samples = num_bytes / sizeof(short); - short *data = array; + unsigned short *data = array; for (i = 0; i < num_samples; i++) { data[i] = le16_to_cpu(data[i]); diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c index 579b74e471d9..fce9acfe8084 100644 --- a/drivers/staging/comedi/drivers/das16m1.c +++ b/drivers/staging/comedi/drivers/das16m1.c @@ -131,18 +131,18 @@ struct das16m1_private_struct { * 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 short ai_buffer[FIFO_SIZE]; unsigned int divisor1; /* divides master clock to obtain conversion speed */ unsigned int divisor2; /* divides master clock to obtain conversion speed */ unsigned long extra_iobase; }; -static inline short munge_sample(short data) +static inline unsigned short munge_sample(unsigned short data) { return (data >> 4) & 0xfff; } -static void munge_sample_array(short *array, unsigned int num_elements) +static void munge_sample_array(unsigned short *array, unsigned int num_elements) { unsigned int i; diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c index f753a10c6549..1880038956d0 100644 --- a/drivers/staging/comedi/drivers/das1800.c +++ b/drivers/staging/comedi/drivers/das1800.c @@ -438,7 +438,8 @@ struct das1800_private { 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 */ + unsigned short ao_update_bits; /* remembers the last write to the + * 'update' dac */ }; /* analog out range for 'ao' boards */ @@ -501,7 +502,7 @@ static void das1800_handle_fifo_not_empty(struct comedi_device *dev, struct comedi_subdevice *s) { struct das1800_private *devpriv = dev->private; - short dpnt; + unsigned short dpnt; int unipolar; struct comedi_cmd *cmd = &s->async->cmd; @@ -1211,7 +1212,7 @@ static int das1800_ai_rinsn(struct comedi_device *dev, int i, n; int chan, range, aref, chan_range; int timeout = 1000; - short dpnt; + unsigned short dpnt; int conv_flags = 0; unsigned long irq_flags; @@ -1276,7 +1277,7 @@ static int das1800_ao_winsn(struct comedi_device *dev, int chan = CR_CHAN(insn->chanspec); /* int range = CR_RANGE(insn->chanspec); */ int update_chan = thisboard->ao_n_chan - 1; - short output; + unsigned short output; unsigned long irq_flags; /* card expects two's complement data */ diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index e89126a15e53..a01e6b553887 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -226,7 +226,7 @@ struct dt282x_private { const struct comedi_lrange *darangelist[2]; - short ao[2]; + unsigned short ao[2]; volatile int dacsr; /* software copies of registers */ volatile int adcsr; @@ -237,7 +237,7 @@ struct dt282x_private { struct { int chan; - short *buf; /* DMA buffer */ + unsigned short *buf; /* DMA buffer */ volatile int size; /* size of current transfer */ } dma[2]; int dma_maxsize; /* max size of DMA transfer (in bytes) */ @@ -283,7 +283,7 @@ static void dt282x_disable_dma(struct comedi_device *dev); static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2); -static void dt282x_munge(struct comedi_device *dev, short *buf, +static void dt282x_munge(struct comedi_device *dev, unsigned short *buf, unsigned int nbytes) { const struct dt282x_board *board = comedi_board(dev); @@ -496,9 +496,9 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) #if 0 if (adcsr & DT2821_ADDONE) { int ret; - short data; + unsigned short data; - data = (short)inw(dev->iobase + DT2821_ADDAT); + data = inw(dev->iobase + DT2821_ADDAT); data &= (1 << board->adbits) - 1; if (devpriv->ad_2scomp) @@ -796,7 +796,7 @@ static int dt282x_ao_insn_write(struct comedi_device *dev, { const struct dt282x_board *board = comedi_board(dev); struct dt282x_private *devpriv = dev->private; - short d; + unsigned short d; unsigned int chan; chan = CR_CHAN(insn->chanspec); diff --git a/drivers/staging/comedi/drivers/dt3000.c b/drivers/staging/comedi/drivers/dt3000.c index fec911fc8d68..292226eeff92 100644 --- a/drivers/staging/comedi/drivers/dt3000.c +++ b/drivers/staging/comedi/drivers/dt3000.c @@ -331,7 +331,7 @@ static void dt3k_ai_empty_fifo(struct comedi_device *dev, int rear; int count; int i; - short data; + unsigned short data; front = readw(devpriv->io_addr + DPR_AD_Buf_Front); count = front - devpriv->ai_front; diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 64565d4c902d..73af600c1725 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c @@ -85,13 +85,9 @@ for my needs. #define F020_MASK_DACxCN_DACxEN 0x80 enum { - /* A/D D/A DI DO CT */ - DT9812_DEVID_DT9812_10, /* 8 2 8 8 1 +/- 10V */ - DT9812_DEVID_DT9812_2PT5, /* 8 2 8 8 1 0-2.44V */ -#if 0 - DT9812_DEVID_DT9813, /* 16 2 4 4 1 +/- 10V */ - DT9812_DEVID_DT9814 /* 24 2 0 0 1 +/- 10V */ -#endif + /* A/D D/A DI DO CT */ + DT9812_DEVID_DT9812_10, /* 8 2 8 8 1 +/- 10V */ + DT9812_DEVID_DT9812_2PT5, /* 8 2 8 8 1 0-2.44V */ }; enum dt9812_gain { diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c index 8d70f64b1574..e3ff4c438979 100644 --- a/drivers/staging/comedi/drivers/fl512.c +++ b/drivers/staging/comedi/drivers/fl512.c @@ -25,8 +25,7 @@ Configuration options: #define FL512_SIZE 16 /* the size of the used memory */ struct fl512_private { - - short ao_readback[2]; + unsigned short ao_readback[2]; }; static const struct comedi_lrange range_fl512 = { 4, { diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c index 15d87187b590..1e16641ec52d 100644 --- a/drivers/staging/comedi/drivers/icp_multi.c +++ b/drivers/staging/comedi/drivers/icp_multi.c @@ -118,9 +118,7 @@ struct icp_multi_private { 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 short ao_data[4]; /* data output buffer */ unsigned int do_data; /* Remember digital output data */ }; diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index aba7beae8e86..3d12e9135926 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -427,7 +427,7 @@ static int xilinx_download(struct comedi_device *dev) static void me4000_reset(struct comedi_device *dev) { struct me4000_info *info = dev->private; - unsigned long val; + unsigned int val; int chan; /* Make a hardware reset */ @@ -480,9 +480,9 @@ static int me4000_ai_insn_read(struct comedi_device *dev, int rang = CR_RANGE(insn->chanspec); int aref = CR_AREF(insn->chanspec); - unsigned long entry = 0; - unsigned long tmp; - long lval; + unsigned int entry = 0; + unsigned int tmp; + unsigned int lval; if (insn->n == 0) { return 0; @@ -586,7 +586,7 @@ static int me4000_ai_insn_read(struct comedi_device *dev, static int me4000_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { - unsigned long tmp; + unsigned int tmp; /* Stop any running conversion */ tmp = inl(dev->iobase + ME4000_AI_CTRL_REG); @@ -783,7 +783,7 @@ static int ai_prepare(struct comedi_device *dev, unsigned int scan_ticks, unsigned int chan_ticks) { - unsigned long tmp = 0; + unsigned int tmp = 0; /* Write timer arguments */ ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks); @@ -1108,7 +1108,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) struct comedi_subdevice *s = &dev->subdevices[0]; int i; int c = 0; - long lval; + unsigned int lval; if (!dev->attached) return IRQ_NONE; @@ -1252,7 +1252,7 @@ static int me4000_ao_insn_write(struct comedi_device *dev, int chan = CR_CHAN(insn->chanspec); int rang = CR_RANGE(insn->chanspec); int aref = CR_AREF(insn->chanspec); - unsigned long tmp; + unsigned int tmp; if (insn->n == 0) { return 0; diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c index c77d34306119..63c847932eb8 100644 --- a/drivers/staging/comedi/drivers/ni_at_a2150.c +++ b/drivers/staging/comedi/drivers/ni_at_a2150.c @@ -154,7 +154,7 @@ 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 */ + uint16_t *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 */ @@ -192,7 +192,7 @@ static irqreturn_t a2150_interrupt(int irq, void *d) struct comedi_async *async; struct comedi_cmd *cmd; unsigned int max_points, num_points, residue, leftover; - short dpnt; + unsigned short dpnt; static const int sample_size = sizeof(devpriv->dma_buffer[0]); if (!dev->attached) { diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index e91570dd6b0d..0512445df08e 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -893,7 +893,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int labpc_drain_fifo(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; - short data; + unsigned short data; struct comedi_async *async = dev->read_subdev->async; const int timeout = 10000; unsigned int i; diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index b9df2eeae6fb..5113397bfecf 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -1292,7 +1292,7 @@ static void ni_ao_fifo_load(struct comedi_device *dev, struct comedi_cmd *cmd = &async->cmd; int chan; int i; - short d; + unsigned short d; u32 packed_data; int range; int err = 1; @@ -1403,7 +1403,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev, int i; if (board->reg_type == ni_reg_611x) { - short data[2]; + unsigned short data[2]; u32 dl; for (i = 0; i < n / 2; i++) { @@ -1420,7 +1420,7 @@ static void ni_ai_fifo_read(struct comedi_device *dev, cfc_write_to_buffer(s, data[0]); } } else if (board->reg_type == ni_reg_6143) { - short data[2]; + unsigned short data[2]; u32 dl; /* This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed */ @@ -1511,9 +1511,9 @@ static void ni_handle_fifo_dregs(struct comedi_device *dev) const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv = dev->private; struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; - short data[2]; + unsigned short data[2]; u32 dl; - short fifo_empty; + unsigned short fifo_empty; int i; if (board->reg_type == ni_reg_611x) { @@ -1577,7 +1577,7 @@ static void get_last_sample_611x(struct comedi_device *dev) const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv __maybe_unused = dev->private; struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; - short data; + unsigned short data; u32 dl; if (board->reg_type != ni_reg_611x) @@ -1596,7 +1596,7 @@ static void get_last_sample_6143(struct comedi_device *dev) const struct ni_board_struct *board = comedi_board(dev); struct ni_private *devpriv __maybe_unused = dev->private; struct comedi_subdevice *s = &dev->subdevices[NI_AI_SUBDEV]; - short data; + unsigned short data; u32 dl; if (board->reg_type != ni_reg_6143) @@ -1621,7 +1621,7 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_async *async = s->async; unsigned int i; unsigned int length = num_bytes / bytes_per_sample(s); - short *array = data; + unsigned short *array = data; unsigned int *larray = data; for (i = 0; i < length; i++) { @@ -2873,7 +2873,7 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int i; unsigned int offset; unsigned int length = num_bytes / sizeof(short); - short *array = data; + unsigned short *array = data; offset = 1 << (board->aobits - 1); for (i = 0; i < length; i++) { diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index b6283a8a7cd4..e3a8fa96d9b3 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -406,9 +406,9 @@ static irqreturn_t nidio_interrupt(int irq, void *d) struct mite_struct *mite = devpriv->mite; /* int i, j; */ - long int AuxData = 0; - short data1 = 0; - short data2 = 0; + unsigned int auxdata = 0; + unsigned short data1 = 0; + unsigned short data2 = 0; int flags; int status; int work = 0; @@ -481,11 +481,11 @@ static irqreturn_t nidio_interrupt(int irq, void *d) ); goto out; } - AuxData = + auxdata = readl(devpriv->mite->daq_io_addr + Group_1_FIFO); - data1 = AuxData & 0xffff; - data2 = (AuxData & 0xffff0000) >> 16; + data1 = auxdata & 0xffff; + data2 = (auxdata & 0xffff0000) >> 16; comedi_buf_put(async, data1); comedi_buf_put(async, data2); /* DPRINTK("read:%d, %d\n",data1,data2); */ diff --git a/drivers/staging/comedi/drivers/ni_stc.h b/drivers/staging/comedi/drivers/ni_stc.h index 11bf0aab82ea..f0630b7897b5 100644 --- a/drivers/staging/comedi/drivers/ni_stc.h +++ b/drivers/staging/comedi/drivers/ni_stc.h @@ -1491,7 +1491,7 @@ struct ni_board_struct { unsigned short pwm_up_count; \ unsigned short pwm_down_count; \ \ - short ai_fifo_buffer[0x2000]; \ + unsigned short ai_fifo_buffer[0x2000]; \ uint8_t eeprom_buffer[M_SERIES_EEPROM_SIZE]; \ uint32_t serial_number; \ \ diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index 89982fb52e50..f0fc123ef566 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -213,7 +213,7 @@ static irqreturn_t pcl711_interrupt(int irq, void *d) outb(PCL711_INT_STAT_CLR, dev->iobase + PCL711_INT_STAT_REG); - if (comedi_buf_put(s->async, (short)data) == 0) { + if (comedi_buf_put(s->async, data) == 0) { s->async->events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR; } else { s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c index 530aee14f07a..03315abcca19 100644 --- a/drivers/staging/comedi/drivers/pcl812.c +++ b/drivers/staging/comedi/drivers/pcl812.c @@ -355,7 +355,6 @@ struct pcl812_private { 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 */ @@ -661,7 +660,6 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 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; @@ -831,7 +829,8 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d) ============================================================================== */ static void transfer_from_dma_buf(struct comedi_device *dev, - struct comedi_subdevice *s, short *ptr, + struct comedi_subdevice *s, + unsigned short *ptr, unsigned int bufptr, unsigned int len) { struct pcl812_private *devpriv = dev->private; @@ -869,9 +868,9 @@ static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d) struct comedi_subdevice *s = &dev->subdevices[0]; unsigned long dma_flags; int len, bufptr; - short *ptr; + unsigned short *ptr; - ptr = (short *)devpriv->dmabuf[devpriv->next_dma_buf]; + ptr = (unsigned short *)devpriv->dmabuf[devpriv->next_dma_buf]; len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) - devpriv->ai_poll_ptr; diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c index 2fd9b178e0c6..ab9d2bd26a20 100644 --- a/drivers/staging/comedi/drivers/pcl816.c +++ b/drivers/staging/comedi/drivers/pcl816.c @@ -229,7 +229,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d) struct comedi_device *dev = d; struct pcl816_private *devpriv = dev->private; struct comedi_subdevice *s = &dev->subdevices[0]; - int low, hi; + unsigned char low, hi; int timeout = 50; /* wait max 50us */ while (timeout--) { @@ -281,7 +281,8 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d) analog input dma mode 1 & 3, 816 cards */ static void transfer_from_dma_buf(struct comedi_device *dev, - struct comedi_subdevice *s, short *ptr, + struct comedi_subdevice *s, + unsigned short *ptr, unsigned int bufptr, unsigned int len) { struct pcl816_private *devpriv = dev->private; @@ -324,7 +325,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d) struct comedi_subdevice *s = &dev->subdevices[0]; int len, bufptr, this_dma_buf; unsigned long dma_flags; - short *ptr; + unsigned short *ptr; disable_dma(devpriv->dma); this_dma_buf = devpriv->next_dma_buf; @@ -352,7 +353,7 @@ static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d) devpriv->dma_runs_to_end--; outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */ - ptr = (short *)devpriv->dmabuf[this_dma_buf]; + ptr = (unsigned short *)devpriv->dmabuf[this_dma_buf]; len = (devpriv->hwdmasize[0] >> 1) - devpriv->ai_poll_ptr; bufptr = devpriv->ai_poll_ptr; @@ -665,7 +666,8 @@ static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) } transfer_from_dma_buf(dev, s, - (short *)devpriv->dmabuf[devpriv->next_dma_buf], + (unsigned short *)devpriv->dmabuf[devpriv-> + next_dma_buf], devpriv->ai_poll_ptr, top2); devpriv->ai_poll_ptr = top1; /* new buffer position */ diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 7be0c946bd7c..9e4d7e860509 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -289,7 +289,6 @@ struct pcl818_private { 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 */ @@ -443,7 +442,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d) struct comedi_device *dev = d; struct pcl818_private *devpriv = dev->private; struct comedi_subdevice *s = &dev->subdevices[0]; - int low; + unsigned char low; int timeout = 50; /* wait max 50us */ while (timeout--) { @@ -505,7 +504,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) struct comedi_subdevice *s = &dev->subdevices[0]; int i, len, bufptr; unsigned long flags; - short *ptr; + unsigned short *ptr; disable_dma(devpriv->dma); devpriv->next_dma_buf = 1 - devpriv->next_dma_buf; @@ -528,7 +527,7 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d) devpriv->dma_runs_to_end--; outb(0, dev->iobase + PCL818_CLRINT); /* clear INT request */ - ptr = (short *)devpriv->dmabuf[1 - devpriv->next_dma_buf]; + ptr = (unsigned short *)devpriv->dmabuf[1 - devpriv->next_dma_buf]; len = devpriv->hwdmasize[0] >> 1; bufptr = 0; @@ -582,7 +581,8 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d) struct comedi_device *dev = d; struct pcl818_private *devpriv = dev->private; struct comedi_subdevice *s = &dev->subdevices[0]; - int i, len, lo; + int i, len; + unsigned char lo; outb(0, dev->iobase + PCL818_FI_INTCLR); /* clear fifo int request */ @@ -1072,7 +1072,6 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 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; diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c index 574443df42da..14cee3ac92c5 100644 --- a/drivers/staging/comedi/drivers/pcmmio.c +++ b/drivers/staging/comedi/drivers/pcmmio.c @@ -553,12 +553,11 @@ static irqreturn_t interrupt_pcmmio(int irq, void *d) val |= (1U << n); } /* Write the scan to the buffer. */ - if (comedi_buf_put(s->async, ((short *)&val)[0]) + if (comedi_buf_put(s->async, val) && comedi_buf_put (s->async, - ((short *) - &val)[1])) { + val >> 16)) { s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); } else { /* Overflow! Stop acquisition!! */ @@ -846,7 +845,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, CR_RANGE(insn->chanspec), aref = CR_AREF(insn->chanspec); unsigned char command_byte = 0; unsigned iooffset = 0; - short sample, adc_adjust = 0; + unsigned short sample, adc_adjust = 0; if (chan > 7) chan -= 8, iooffset = 4; /* diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 67e2bb1d66f0..954fa96a50ac 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -315,8 +315,8 @@ static void pcmuio_handle_intr_subdev(struct comedi_device *dev, } /* Write the scan to the buffer. */ - if (comedi_buf_put(s->async, ((short *)&val)[0]) && - comedi_buf_put(s->async, ((short *)&val)[1])) { + if (comedi_buf_put(s->async, val) && + comedi_buf_put(s->async, val >> 16)) { s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); } else { /* Overflow! Stop acquisition!! */ diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index ece3031711eb..96a46954b3c0 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -208,8 +208,7 @@ static enum irqreturn daqp_interrupt(int irq, void *dev_id) case buffer: while (!((status = inb(dev->iobase + DAQP_STATUS)) & DAQP_STATUS_FIFO_EMPTY)) { - - short data; + unsigned short data; if (status & DAQP_STATUS_DATA_LOST) { s->async->events |= diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c index 3ec6632949bd..0ae2d6175471 100644 --- a/drivers/staging/comedi/drivers/rtd520.c +++ b/drivers/staging/comedi/drivers/rtd520.c @@ -602,7 +602,7 @@ static int rtd_ai_rinsn(struct comedi_device *dev, /* convert n samples */ for (n = 0; n < insn->n; n++) { - s16 d; + unsigned short d; /* trigger conversion */ writew(0, devpriv->las0 + LAS0_ADC); @@ -621,9 +621,8 @@ static int rtd_ai_rinsn(struct comedi_device *dev, d = d >> 3; /* low 3 bits are marker lines */ if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar, 0)) /* convert to comedi unsigned data */ - data[n] = d + 2048; - else - data[n] = d; + d = comedi_offset_munge(s, d); + data[n] = d & s->maxdata; } /* return the number of samples read/written */ @@ -643,8 +642,7 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, int ii; for (ii = 0; ii < count; ii++) { - short sample; - s16 d; + unsigned short d; if (0 == devpriv->ai_count) { /* done */ d = readw(devpriv->las1 + LAS1_ADC_FIFO); @@ -654,13 +652,12 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s, d = readw(devpriv->las1 + LAS1_ADC_FIFO); d = d >> 3; /* low 3 bits are marker lines */ if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar, - s->async->cur_chan)) { + s->async->cur_chan)) /* convert to comedi unsigned data */ - sample = d + 2048; - } else - sample = d; + d = comedi_offset_munge(s, d); + d &= s->maxdata; - if (!comedi_buf_put(s->async, sample)) + if (!comedi_buf_put(s->async, d)) return -1; if (devpriv->ai_count > 0) /* < 0, means read forever */ @@ -677,8 +674,7 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) struct rtd_private *devpriv = dev->private; while (readl(devpriv->las0 + LAS0_ADC) & FS_ADC_NOT_EMPTY) { - short sample; - s16 d = readw(devpriv->las1 + LAS1_ADC_FIFO); + unsigned short d = readw(devpriv->las1 + LAS1_ADC_FIFO); if (0 == devpriv->ai_count) { /* done */ continue; /* read rest */ @@ -686,13 +682,12 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s) d = d >> 3; /* low 3 bits are marker lines */ if (CHAN_ARRAY_TEST(devpriv->chan_is_bipolar, - s->async->cur_chan)) { + s->async->cur_chan)) /* convert to comedi unsigned data */ - sample = d + 2048; - } else - sample = d; + d = comedi_offset_munge(s, d); + d &= s->maxdata; - if (!comedi_buf_put(s->async, sample)) + if (!comedi_buf_put(s->async, d)) return -1; if (devpriv->ai_count > 0) /* < 0, means read forever */ diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 4eb4e7160bc3..d9aba7ce862d 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -1,63 +1,63 @@ /* - comedi/drivers/s626.c - Sensoray s626 Comedi driver - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <[email protected]> - - Based on Sensoray Model 626 Linux driver Version 0.2 - Copyright (C) 2002-2004 Sensoray Co., 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. -*/ + * comedi/drivers/s626.c + * Sensoray s626 Comedi driver + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <[email protected]> + * + * Based on Sensoray Model 626 Linux driver Version 0.2 + * Copyright (C) 2002-2004 Sensoray Co., 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. + */ /* -Driver: s626 -Description: Sensoray 626 driver -Devices: [Sensoray] 626 (s626) -Authors: Gianluca Palli <[email protected]>, -Updated: Fri, 15 Feb 2008 10:28:42 +0000 -Status: experimental - -Configuration options: not applicable, uses PCI auto config - -INSN_CONFIG instructions: - analog input: - none - - analog output: - none - - digital channel: - s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels - supported configuration options: - INSN_CONFIG_DIO_QUERY - COMEDI_INPUT - COMEDI_OUTPUT - - encoder: - Every channel must be configured before reading. - - 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 - - comedi_do_insn(cf,&insn); //executing configuration -*/ + * Driver: s626 + * Description: Sensoray 626 driver + * Devices: [Sensoray] 626 (s626) + * Authors: Gianluca Palli <[email protected]>, + * Updated: Fri, 15 Feb 2008 10:28:42 +0000 + * Status: experimental + + * Configuration options: not applicable, uses PCI auto config + + * INSN_CONFIG instructions: + * analog input: + * none + * + * analog output: + * none + * + * digital channel: + * s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels + * supported configuration options: + * INSN_CONFIG_DIO_QUERY + * COMEDI_INPUT + * COMEDI_OUTPUT + * + * encoder: + * Every channel must be configured before reading. + * + * 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 + * + * comedi_do_insn(cf,&insn); //executing configuration + */ #include <linux/module.h> #include <linux/delay.h> @@ -71,68 +71,91 @@ INSN_CONFIG instructions: #include "comedi_fc.h" #include "s626.h" -#define PCI_VENDOR_ID_S626 0x1131 -#define PCI_DEVICE_ID_S626 0x7146 -#define PCI_SUBVENDOR_ID_S626 0x6000 -#define PCI_SUBDEVICE_ID_S626 0x0272 +struct s626_buffer_dma { + dma_addr_t physical_base; + void *logical_base; +}; struct s626_private { void __iomem *mmio; - uint8_t ai_cmd_running; /* ai_cmd is running */ - uint8_t ai_continous; /* continous acquisition */ - int ai_sample_count; /* number of samples to acquire */ - 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 */ - /* Charge Enabled (0 or WRMISC2_CHARGE_ENABLE). */ - uint32_t I2CAdrs; - /* I2C device address for onboard EEPROM (board rev dependent). */ - /* short I2Cards; */ + uint8_t ai_cmd_running; /* ai_cmd is running */ + uint8_t ai_continuous; /* continuous acquisition */ + int ai_sample_count; /* number of samples to acquire */ + 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 counter_int_enabs; /* counter interrupt enable mask + * for MISC2 register */ + uint8_t adc_items; /* number of items in ADC poll list */ + struct s626_buffer_dma rps_buf; /* DMA buffer used to hold ADC (RPS1) + * program */ + struct s626_buffer_dma ana_buf; /* DMA buffer used to receive ADC data + * and hold DAC data */ + uint32_t *dac_wbuf; /* pointer to logical adrs of DMA buffer + * used to hold DAC data */ + uint16_t dacpol; /* image of DAC polarity register */ + uint8_t trim_setpoint[12]; /* images of TrimDAC setpoints */ + uint32_t i2c_adrs; /* I2C device address for onboard EEPROM + * (board rev dependent) */ unsigned int ao_readback[S626_DAC_CHANNELS]; }; -/* 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. */ +/* COUNTER OBJECT ------------------------------------------------ */ +struct s626_enc_info { + /* Pointers to functions that differ for A and B counters: */ + /* Return clock enable. */ + uint16_t(*get_enable)(struct comedi_device *dev, + const struct s626_enc_info *k); + /* Return interrupt source. */ + uint16_t(*get_int_src)(struct comedi_device *dev, + const struct s626_enc_info *k); + /* Return preload trigger source. */ + uint16_t(*get_load_trig)(struct comedi_device *dev, + const struct s626_enc_info *k); + /* Return standardized operating mode. */ + uint16_t(*get_mode)(struct comedi_device *dev, + const struct s626_enc_info *k); + /* Generate soft index strobe. */ + void (*pulse_index)(struct comedi_device *dev, + const struct s626_enc_info *k); + /* Program clock enable. */ + void (*set_enable)(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t enab); + /* Program interrupt source. */ + void (*set_int_src)(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t int_source); + /* Program preload trigger source. */ + void (*set_load_trig)(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t trig); + /* Program standardized operating mode. */ + void (*set_mode)(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t setup, + uint16_t disable_int_src); + /* Reset event capture flags. */ + void (*reset_cap_flags)(struct comedi_device *dev, + const struct s626_enc_info *k); + + uint16_t my_cra; /* address of CRA register */ + uint16_t my_crb; /* address of CRB register */ + uint16_t my_latch_lsw; /* address of Latch least-significant-word + * register */ + uint16_t my_event_bits[4]; /* bit translations for IntSrc -->RDMISC2 */ }; -#define encpriv ((struct enc_private *)(dev->subdevices+5)->private) - -/* 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) } +/* Counter overflow/index event flag masks for RDMISC2. */ +#define S626_INDXMASK(C) (1 << (((C) > 2) ? ((C) * 2 - 1) : ((C) * 2 + 4))) +#define S626_OVERMASK(C) (1 << (((C) > 2) ? ((C) * 2 + 5) : ((C) * 2 + 10))) +#define S626_EVBITS(C) { 0, S626_OVERMASK(C), S626_INDXMASK(C), \ + S626_OVERMASK(C) | S626_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 s626_event_bits[][4] = + * { S626_EVBITS(0), S626_EVBITS(1), S626_EVBITS(2), S626_EVBITS(3), + * S626_EVBITS(4), S626_EVBITS(5) }; + */ /* * Enable/disable a function or test status bit(s) that are accessed @@ -144,6 +167,7 @@ static void s626_mc_enable(struct comedi_device *dev, struct s626_private *devpriv = dev->private; unsigned int val = (cmd << 16) | cmd; + mmiowb(); writel(val, devpriv->mmio + reg); } @@ -153,6 +177,7 @@ static void s626_mc_disable(struct comedi_device *dev, struct s626_private *devpriv = dev->private; writel(cmd << 16 , devpriv->mmio + reg); + mmiowb(); } static bool s626_mc_test(struct comedi_device *dev, @@ -166,15 +191,10 @@ static bool s626_mc_test(struct comedi_device *dev, return (val & cmd) ? true : false; } -#define BUGFIX_STREG(REGADRS) (REGADRS - 4) +#define S626_BUGFIX_STREG(REGADRS) ((REGADRS) - 4) -/* Write a time slot control record to TSL2. */ -#define VECTPORT(VECTNUM) (P_TSL2 + ((VECTNUM) << 2)) - -/* 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)) +/* Write a time slot control record to TSL2. */ +#define S626_VECTPORT(VECTNUM) (S626_P_TSL2 + ((VECTNUM) << 2)) static const struct comedi_lrange s626_range_table = { 2, { @@ -183,178 +203,182 @@ static const struct comedi_lrange s626_range_table = { } }; -/* Execute a DEBI transfer. This must be called from within a */ -/* critical section. */ -static void DEBItransfer(struct comedi_device *dev) +/* + * Execute a DEBI transfer. This must be called from within a critical section. + */ +static void s626_debi_transfer(struct comedi_device *dev) { struct s626_private *devpriv = dev->private; /* Initiate upload of shadow RAM to DEBI control register */ - s626_mc_enable(dev, MC2_UPLD_DEBI, P_MC2); + s626_mc_enable(dev, S626_MC2_UPLD_DEBI, S626_P_MC2); /* * Wait for completion of upload from shadow RAM to * DEBI control register. */ - while (!s626_mc_test(dev, MC2_UPLD_DEBI, P_MC2)) + while (!s626_mc_test(dev, S626_MC2_UPLD_DEBI, S626_P_MC2)) ; /* Wait until DEBI transfer is done */ - while (readl(devpriv->mmio + P_PSR) & PSR_DEBI_S) + while (readl(devpriv->mmio + S626_P_PSR) & S626_PSR_DEBI_S) ; } -/* Initialize the DEBI interface for all transfers. */ - -static uint16_t DEBIread(struct comedi_device *dev, uint16_t addr) +/* + * Read a value from a gate array register. + */ +static uint16_t s626_debi_read(struct comedi_device *dev, uint16_t addr) { struct s626_private *devpriv = dev->private; /* Set up DEBI control register value in shadow RAM */ - writel(DEBI_CMD_RDWORD | addr, devpriv->mmio + P_DEBICMD); + writel(S626_DEBI_CMD_RDWORD | addr, devpriv->mmio + S626_P_DEBICMD); /* Execute the DEBI transfer. */ - DEBItransfer(dev); + s626_debi_transfer(dev); - return readl(devpriv->mmio + P_DEBIAD); + return readl(devpriv->mmio + S626_P_DEBIAD); } -/* Write a value to a gate array register. */ -static void DEBIwrite(struct comedi_device *dev, uint16_t addr, uint16_t wdata) +/* + * Write a value to a gate array register. + */ +static void s626_debi_write(struct comedi_device *dev, uint16_t addr, + uint16_t wdata) { struct s626_private *devpriv = dev->private; /* Set up DEBI control register value in shadow RAM */ - writel(DEBI_CMD_WRWORD | addr, devpriv->mmio + P_DEBICMD); - writel(wdata, devpriv->mmio + P_DEBIAD); + writel(S626_DEBI_CMD_WRWORD | addr, devpriv->mmio + S626_P_DEBICMD); + writel(wdata, devpriv->mmio + S626_P_DEBIAD); /* Execute the DEBI transfer. */ - DEBItransfer(dev); + s626_debi_transfer(dev); } -/* Replace the specified bits in a gate array register. Imports: 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, unsigned int addr, - unsigned int mask, unsigned int wdata) +static void s626_debi_replace(struct comedi_device *dev, unsigned int addr, + unsigned int mask, unsigned int wdata) { struct s626_private *devpriv = dev->private; unsigned int val; addr &= 0xffff; - writel(DEBI_CMD_RDWORD | addr, devpriv->mmio + P_DEBICMD); - DEBItransfer(dev); + writel(S626_DEBI_CMD_RDWORD | addr, devpriv->mmio + S626_P_DEBICMD); + s626_debi_transfer(dev); - writel(DEBI_CMD_WRWORD | addr, devpriv->mmio + P_DEBICMD); - val = readl(devpriv->mmio + P_DEBIAD); + writel(S626_DEBI_CMD_WRWORD | addr, devpriv->mmio + S626_P_DEBICMD); + val = readl(devpriv->mmio + S626_P_DEBIAD); val &= mask; val |= wdata; - writel(val & 0xffff, devpriv->mmio + P_DEBIAD); - DEBItransfer(dev); + writel(val & 0xffff, devpriv->mmio + S626_P_DEBIAD); + s626_debi_transfer(dev); } /* ************** EEPROM ACCESS FUNCTIONS ************** */ -static uint32_t I2Chandshake(struct comedi_device *dev, uint32_t val) +static uint32_t s626_i2c_handshake(struct comedi_device *dev, uint32_t val) { struct s626_private *devpriv = dev->private; unsigned int ctrl; /* Write I2C command to I2C Transfer Control shadow register */ - writel(val, devpriv->mmio + P_I2CCTRL); + writel(val, devpriv->mmio + S626_P_I2CCTRL); /* * Upload I2C shadow registers into working registers and * wait for upload confirmation. */ - s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2); - while (!s626_mc_test(dev, MC2_UPLD_IIC, P_MC2)) + s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); + while (!s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2)) ; /* Wait until I2C bus transfer is finished or an error occurs */ do { - ctrl = readl(devpriv->mmio + P_I2CCTRL); - } while ((ctrl & (I2C_BUSY | I2C_ERR)) == I2C_BUSY); + ctrl = readl(devpriv->mmio + S626_P_I2CCTRL); + } while ((ctrl & (S626_I2C_BUSY | S626_I2C_ERR)) == S626_I2C_BUSY); /* Return non-zero if I2C error occurred */ - return ctrl & I2C_ERR; + return ctrl & S626_I2C_ERR; } -/* Read uint8_t from EEPROM. */ -static uint8_t I2Cread(struct comedi_device *dev, uint8_t addr) +/* Read uint8_t from EEPROM. */ +static uint8_t s626_i2c_read(struct comedi_device *dev, uint8_t addr) { struct s626_private *devpriv = dev->private; - /* 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: + * Byte2 = I2C command: write to I2C EEPROM device. + * Byte1 = EEPROM internal target address. + * Byte0 = Not sent. + */ + if (s626_i2c_handshake(dev, S626_I2C_B2(S626_I2C_ATTRSTART, + devpriv->i2c_adrs) | + S626_I2C_B1(S626_I2C_ATTRSTOP, addr) | + S626_I2C_B0(S626_I2C_ATTRNOP, 0))) + /* Abort function and declare error if handshake failed. */ 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: + * Byte2 = I2C command: read from I2C EEPROM device. + * Byte1 receives uint8_t from EEPROM. + * Byte0 = Not sent. + */ + if (s626_i2c_handshake(dev, S626_I2C_B2(S626_I2C_ATTRSTART, + (devpriv->i2c_adrs | 1)) | + S626_I2C_B1(S626_I2C_ATTRSTOP, 0) | + S626_I2C_B0(S626_I2C_ATTRNOP, 0))) + /* Abort function and declare error if handshake failed. */ return 0; - } - return (readl(devpriv->mmio + P_I2CCTRL) >> 16) & 0xff; + return (readl(devpriv->mmio + S626_P_I2CCTRL) >> 16) & 0xff; } /* *********** DAC FUNCTIONS *********** */ -/* 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. */ +static const uint8_t s626_trimchan[] = { 10, 9, 8, 3, 2, 7, 6, 1, 0, 5, 4 }; -/* 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. */ -static uint8_t trimadrs[] = { 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 }; +/* TrimDac LogicalChan-to-EepromAdrs mapping table. */ +static const uint8_t s626_trimadrs[] = { + 0x40, 0x41, 0x42, 0x50, 0x51, 0x52, 0x53, 0x60, 0x61, 0x62, 0x63 +}; -/* Private helper function: Transmit serial data to DAC via Audio +/* + * 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. + * dacpol contains valid target image. */ -static void SendDAC(struct comedi_device *dev, uint32_t val) +static void s626_send_dac(struct comedi_device *dev, uint32_t val) { struct s626_private *devpriv = dev->private; /* START THE SERIAL CLOCK RUNNING ------------- */ - /* Assert DAC polarity control and enable gating of DAC serial clock + /* + * 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 + * because the following s626_debi_write 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); + s626_debi_write(dev, S626_LP_DACPOL, devpriv->dacpol); /* TRANSFER OUTPUT DWORD VALUE INTO A2'S OUTPUT FIFO ---------------- */ /* Copy DAC setpoint value to DAC's output DMA buffer. */ - - /* writel(val, devpriv->mmio + (uint32_t)devpriv->pDacWBuf); */ - *devpriv->pDacWBuf = val; + /* writel(val, devpriv->mmio + (uint32_t)devpriv->dac_wbuf); */ + *devpriv->dac_wbuf = val; /* * Enable the output DMA transfer. This will cause the DMAC to copy @@ -362,56 +386,62 @@ static void SendDAC(struct comedi_device *dev, uint32_t val) * then immediately terminate because the protection address is * reached upon transfer of the first DWORD value. */ - s626_mc_enable(dev, MC1_A2OUT, P_MC1); + s626_mc_enable(dev, S626_MC1_A2OUT, S626_P_MC1); - /* 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. */ - writel(ISR_AFOU, devpriv->mmio + P_ISR); + writel(S626_ISR_AFOU, devpriv->mmio + S626_P_ISR); - /* Wait for the DMA transfer to finish so that there will be data + /* + * 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 (readl(devpriv->mmio + P_MC1) & MC1_A2OUT) + while (readl(devpriv->mmio + S626_P_MC1) & S626_MC1_A2OUT) ; /* START THE OUTPUT STREAM TO THE TARGET DAC -------------------- */ - /* FIFO data is now available, so we enable execution of time slots + /* + * 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. */ - writel(XSD2 | RSD3 | SIB_A2, devpriv->mmio + VECTPORT(0)); + writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2, + devpriv->mmio + S626_VECTPORT(0)); - /* Wait for slot 1 to execute to ensure that the Packet will be + /* + * 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 (!(readl(devpriv->mmio + P_SSR) & SSR_AF2_OUT)) + while (!(readl(devpriv->mmio + S626_P_SSR) & S626_SSR_AF2_OUT)) ; - /* Set up to trap execution at slot 0 when the TSL sequencer cycles + /* + * 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. */ - writel(XSD2 | XFIFO_2 | RSD2 | SIB_A2 | EOS, - devpriv->mmio + VECTPORT(0)); + writel(S626_XSD2 | S626_XFIFO_2 | S626_RSD2 | S626_SIB_A2 | S626_EOS, + devpriv->mmio + S626_VECTPORT(0)); /* WAIT FOR THE TRANSACTION TO FINISH ----------------------- */ - /* Wait for the TSL to finish executing all time slots before + /* + * 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: * @@ -428,17 +458,19 @@ static void SendDAC(struct comedi_device *dev, uint32_t val) * we test for the FB_BUFFER2 MSB contents to be equal to 0xFF. If * the TSL has not yet finished executing slot 5 ... */ - if (readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000) { - /* The trap was set on time and we are still executing somewhere + if (readl(devpriv->mmio + S626_P_FB_BUFFER2) & 0xff000000) { + /* + * 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 (readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000) + while (readl(devpriv->mmio + S626_P_FB_BUFFER2) & 0xff000000) ; } - /* Either (1) we were too late setting the slot 0 trap; the TSL + /* + * 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 @@ -446,37 +478,46 @@ static void SendDAC(struct comedi_device *dev, uint32_t val) * 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. */ - writel(RSD3 | SIB_A2 | EOS, devpriv->mmio + VECTPORT(0)); + writel(S626_RSD3 | S626_SIB_A2 | S626_EOS, + devpriv->mmio + S626_VECTPORT(0)); - /* Wait for slot 0 to execute, at which time the TSL is setup for + /* + * 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 (!(readl(devpriv->mmio + P_FB_BUFFER2) & 0xff000000)) + while (!(readl(devpriv->mmio + S626_P_FB_BUFFER2) & 0xff000000)) ; } -/* Private helper function: Write setpoint to an application DAC channel. */ -static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata) +/* + * Private helper function: Write setpoint to an application DAC channel. + */ +static void s626_set_dac(struct comedi_device *dev, uint16_t chan, + unsigned short dacdata) { struct s626_private *devpriv = dev->private; - register uint16_t signmask; - register uint32_t WSImage; + uint16_t signmask; + uint32_t ws_image; + uint32_t val; - /* 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; - devpriv->Dacpol |= signmask; - } else - devpriv->Dacpol &= ~signmask; + devpriv->dacpol |= signmask; + } else { + devpriv->dacpol &= ~signmask; + } - /* Limit DAC setpoint value to valid range. */ - if ((uint16_t) dacdata > 0x1FFF) + /* 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 + /* + * 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 @@ -487,140 +528,811 @@ static void SetDAC(struct comedi_device *dev, uint16_t chan, short dacdata) */ /* Choose DAC chip select to be asserted */ - WSImage = (chan & 2) ? WS1 : WS2; + ws_image = (chan & 2) ? S626_WS1 : S626_WS2; /* Slot 2: Transmit high data byte to target DAC */ - writel(XSD2 | XFIFO_1 | WSImage, devpriv->mmio + VECTPORT(2)); + writel(S626_XSD2 | S626_XFIFO_1 | ws_image, + devpriv->mmio + S626_VECTPORT(2)); /* Slot 3: Transmit low data byte to target DAC */ - writel(XSD2 | XFIFO_0 | WSImage, devpriv->mmio + VECTPORT(3)); + writel(S626_XSD2 | S626_XFIFO_0 | ws_image, + devpriv->mmio + S626_VECTPORT(3)); /* Slot 4: Transmit to non-existent TrimDac channel to keep clock */ - writel(XSD2 | XFIFO_3 | WS3, devpriv->mmio + VECTPORT(4)); + writel(S626_XSD2 | S626_XFIFO_3 | S626_WS3, + devpriv->mmio + S626_VECTPORT(4)); /* Slot 5: running after writing target DAC's low data byte */ - writel(XSD2 | XFIFO_2 | WS3 | EOS, devpriv->mmio + VECTPORT(5)); + writel(S626_XSD2 | S626_XFIFO_2 | S626_WS3 | S626_EOS, + devpriv->mmio + S626_VECTPORT(5)); - /* Construct and transmit target DAC's serial packet: - * ( A10D DDDD ),( DDDD DDDD ),( 0x0F ),( 0x00 ) where A is chan<0>, + /* + * 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. */ - + val = 0x0F000000; /* Continue clock after target DAC data + * (write to non-existent trimdac). */ + val |= 0x00004000; /* Address the two main dual-DAC devices + * (TSL's chip select enables target device). */ + val |= ((uint32_t)(chan & 1) << 15); /* Address the DAC channel + * within the device. */ + val |= (uint32_t)dacdata; /* Include DAC setpoint data. */ + s626_send_dac(dev, val); } -static void WriteTrimDAC(struct comedi_device *dev, uint8_t LogicalChan, - uint8_t DacData) +static void s626_write_trim_dac(struct comedi_device *dev, uint8_t logical_chan, + uint8_t dac_data) { struct s626_private *devpriv = dev->private; uint32_t chan; - /* Save the new setpoint in case the application needs to read it back later. */ - devpriv->TrimSetpoint[LogicalChan] = (uint8_t) DacData; + /* + * Save the new setpoint in case the application needs to read it back + * later. + */ + devpriv->trim_setpoint[logical_chan] = (uint8_t)dac_data; - /* Map logical channel number to physical channel number. */ - chan = (uint32_t) trimchan[LogicalChan]; + /* Map logical channel number to physical channel number. */ + chan = s626_trimchan[logical_chan]; - /* Set up TSL2 records for TrimDac write operation. All slots shift + /* + * 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. */ /* Slot 2: Send high uint8_t to target TrimDac */ - writel(XSD2 | XFIFO_1 | WS3, devpriv->mmio + VECTPORT(2)); + writel(S626_XSD2 | S626_XFIFO_1 | S626_WS3, + devpriv->mmio + S626_VECTPORT(2)); /* Slot 3: Send low uint8_t to target TrimDac */ - writel(XSD2 | XFIFO_0 | WS3, devpriv->mmio + VECTPORT(3)); + writel(S626_XSD2 | S626_XFIFO_0 | S626_WS3, + devpriv->mmio + S626_VECTPORT(3)); /* Slot 4: Send NOP high uint8_t to DAC0 to keep clock running */ - writel(XSD2 | XFIFO_3 | WS1, devpriv->mmio + VECTPORT(4)); + writel(S626_XSD2 | S626_XFIFO_3 | S626_WS1, + devpriv->mmio + S626_VECTPORT(4)); /* Slot 5: Send NOP low uint8_t to DAC0 */ - writel(XSD2 | XFIFO_2 | WS1 | EOS, devpriv->mmio + VECTPORT(5)); + writel(S626_XSD2 | S626_XFIFO_2 | S626_WS1 | S626_EOS, + devpriv->mmio + S626_VECTPORT(5)); - /* Construct and transmit target DAC's serial packet: - * ( 0000 AAAA ), ( DDDD DDDD ),( 0x00 ),( 0x00 ) where A<3:0> is the + /* + * 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. */ + /* + * Address the DAC channel within the trimdac device. + * Include DAC setpoint data. + */ + s626_send_dac(dev, (chan << 8) | dac_data); } -static void LoadTrimDACs(struct comedi_device *dev) +static void s626_load_trim_dacs(struct comedi_device *dev) { - register uint8_t i; + uint8_t i; - /* Copy TrimDac setpoint values from EEPROM to TrimDacs. */ - for (i = 0; i < ARRAY_SIZE(trimchan); i++) - WriteTrimDAC(dev, i, I2Cread(dev, trimadrs[i])); + /* Copy TrimDac setpoint values from EEPROM to TrimDacs. */ + for (i = 0; i < ARRAY_SIZE(s626_trimchan); i++) + s626_write_trim_dac(dev, i, + s626_i2c_read(dev, s626_trimadrs[i])); } /* ****** COUNTER FUNCTIONS ******* */ -/* All counter functions address a specific counter by means of the + +/* + * 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. */ -/* Read a counter's output latch. */ -static uint32_t ReadLatch(struct comedi_device *dev, struct enc_private *k) +/* + * Read a counter's output latch. + */ +static uint32_t s626_read_latch(struct comedi_device *dev, + const struct s626_enc_info *k) { - register uint32_t value; + uint32_t value; - /* Latch counts and fetch LSW of latched counts value. */ - value = (uint32_t) DEBIread(dev, k->MyLatchLsw); + /* Latch counts and fetch LSW of latched counts value. */ + value = s626_debi_read(dev, k->my_latch_lsw); - /* Fetch MSW of latched counts and combine with LSW. */ - value |= ((uint32_t) DEBIread(dev, k->MyLatchLsw + 2) << 16); + /* Fetch MSW of latched counts and combine with LSW. */ + value |= ((uint32_t)s626_debi_read(dev, k->my_latch_lsw + 2) << 16); - /* Return latched counts. */ + /* Return latched counts. */ return value; } -/* Return/set a counter pair's latch trigger source. 0: On read +/* + * 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(struct comedi_device *dev, struct enc_private *k, - uint16_t value) +static void s626_set_latch_source(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t value) { - DEBIreplace(dev, k->MyCRB, - ~(CRBMSK_INTCTRL | CRBMSK_LATCHSRC), - value << CRBBIT_LATCHSRC); + s626_debi_replace(dev, k->my_crb, + ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_LATCHSRC), + value << S626_CRBBIT_LATCHSRC); } -/* Write value into counter preload register. */ -static void Preload(struct comedi_device *dev, struct enc_private *k, - uint32_t value) +/* + * Write value into counter preload register. + */ +static void s626_preload(struct comedi_device *dev, + const struct s626_enc_info *k, uint32_t value) { - DEBIwrite(dev, (uint16_t) (k->MyLatchLsw), (uint16_t) value); - DEBIwrite(dev, (uint16_t) (k->MyLatchLsw + 2), - (uint16_t) (value >> 16)); + s626_debi_write(dev, k->my_latch_lsw, value); + s626_debi_write(dev, k->my_latch_lsw + 2, value >> 16); } -static unsigned int s626_ai_reg_to_uint(int data) +/* ****** PRIVATE COUNTER FUNCTIONS ****** */ + +/* + * Reset a counter's index and overflow event capture flags. + */ +static void s626_reset_cap_flags_a(struct comedi_device *dev, + const struct s626_enc_info *k) { - unsigned int tempdata; + s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL, + S626_CRBMSK_INTRESETCMD | S626_CRBMSK_INTRESET_A); +} - tempdata = (data >> 18); - if (tempdata & 0x2000) - tempdata &= 0x1fff; - else - tempdata += (1 << 13); +static void s626_reset_cap_flags_b(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL, + S626_CRBMSK_INTRESETCMD | S626_CRBMSK_INTRESET_B); +} + +/* + * Return counter setup in a format (COUNTER_SETUP) that is consistent + * for both A and B counters. + */ +static uint16_t s626_get_mode_a(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + uint16_t cra; + uint16_t crb; + uint16_t setup; + + /* Fetch CRA and CRB register images. */ + cra = s626_debi_read(dev, k->my_cra); + crb = s626_debi_read(dev, k->my_crb); + + /* + * Populate the standardized counter setup bit fields. + * Note: IndexSrc is restricted to ENC_X or IndxPol. + */ + setup = (cra & S626_STDMSK_LOADSRC) | /* LoadSrc = LoadSrcA. */ + ((crb << (S626_STDBIT_LATCHSRC - S626_CRBBIT_LATCHSRC)) & + S626_STDMSK_LATCHSRC) | /* LatchSrc = LatchSrcA. */ + ((cra << (S626_STDBIT_INTSRC - S626_CRABIT_INTSRC_A)) & + S626_STDMSK_INTSRC) | /* IntSrc = IntSrcA. */ + ((cra << (S626_STDBIT_INDXSRC - (S626_CRABIT_INDXSRC_A + 1))) & + S626_STDMSK_INDXSRC) | /* IndxSrc = IndxSrcA<1>. */ + ((cra >> (S626_CRABIT_INDXPOL_A - S626_STDBIT_INDXPOL)) & + S626_STDMSK_INDXPOL) | /* IndxPol = IndxPolA. */ + ((crb >> (S626_CRBBIT_CLKENAB_A - S626_STDBIT_CLKENAB)) & + S626_STDMSK_CLKENAB); /* ClkEnab = ClkEnabA. */ + + /* Adjust mode-dependent parameters. */ + if (cra & (2 << S626_CRABIT_CLKSRC_A)) { + /* Timer mode (ClkSrcA<1> == 1): */ + /* Indicate Timer mode. */ + setup |= S626_CLKSRC_TIMER << S626_STDBIT_CLKSRC; + /* Set ClkPol to indicate count direction (ClkSrcA<0>). */ + setup |= (cra << (S626_STDBIT_CLKPOL - S626_CRABIT_CLKSRC_A)) & + S626_STDMSK_CLKPOL; + /* ClkMult must be 1x in Timer mode. */ + setup |= S626_MULT_X1 << S626_STDBIT_CLKMULT; + } else { + /* Counter mode (ClkSrcA<1> == 0): */ + /* Indicate Counter mode. */ + setup |= S626_CLKSRC_COUNTER << S626_STDBIT_CLKSRC; + /* Pass through ClkPol. */ + setup |= (cra >> (S626_CRABIT_CLKPOL_A - S626_STDBIT_CLKPOL)) & + S626_STDMSK_CLKPOL; + /* Force ClkMult to 1x if not legal, else pass through. */ + if ((cra & S626_CRAMSK_CLKMULT_A) == + (S626_MULT_X0 << S626_CRABIT_CLKMULT_A)) + setup |= S626_MULT_X1 << S626_STDBIT_CLKMULT; + else + setup |= (cra >> (S626_CRABIT_CLKMULT_A - + S626_STDBIT_CLKMULT)) & + S626_STDMSK_CLKMULT; + } + + /* Return adjusted counter setup. */ + return setup; +} + +static uint16_t s626_get_mode_b(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + uint16_t cra; + uint16_t crb; + uint16_t setup; + + /* Fetch CRA and CRB register images. */ + cra = s626_debi_read(dev, k->my_cra); + crb = s626_debi_read(dev, k->my_crb); + + /* + * Populate the standardized counter setup bit fields. + * Note: IndexSrc is restricted to ENC_X or IndxPol. + */ + setup = ((crb << (S626_STDBIT_INTSRC - S626_CRBBIT_INTSRC_B)) & + S626_STDMSK_INTSRC) | /* IntSrc = IntSrcB. */ + ((crb << (S626_STDBIT_LATCHSRC - S626_CRBBIT_LATCHSRC)) & + S626_STDMSK_LATCHSRC) | /* LatchSrc = LatchSrcB. */ + ((crb << (S626_STDBIT_LOADSRC - S626_CRBBIT_LOADSRC_B)) & + S626_STDMSK_LOADSRC) | /* LoadSrc = LoadSrcB. */ + ((crb << (S626_STDBIT_INDXPOL - S626_CRBBIT_INDXPOL_B)) & + S626_STDMSK_INDXPOL) | /* IndxPol = IndxPolB. */ + ((crb >> (S626_CRBBIT_CLKENAB_B - S626_STDBIT_CLKENAB)) & + S626_STDMSK_CLKENAB) | /* ClkEnab = ClkEnabB. */ + ((cra >> ((S626_CRABIT_INDXSRC_B + 1) - S626_STDBIT_INDXSRC)) & + S626_STDMSK_INDXSRC); /* IndxSrc = IndxSrcB<1>. */ + + /* Adjust mode-dependent parameters. */ + if ((crb & S626_CRBMSK_CLKMULT_B) == + (S626_MULT_X0 << S626_CRBBIT_CLKMULT_B)) { + /* Extender mode (ClkMultB == S626_MULT_X0): */ + /* Indicate Extender mode. */ + setup |= S626_CLKSRC_EXTENDER << S626_STDBIT_CLKSRC; + /* Indicate multiplier is 1x. */ + setup |= S626_MULT_X1 << S626_STDBIT_CLKMULT; + /* Set ClkPol equal to Timer count direction (ClkSrcB<0>). */ + setup |= (cra >> (S626_CRABIT_CLKSRC_B - S626_STDBIT_CLKPOL)) & + S626_STDMSK_CLKPOL; + } else if (cra & (2 << S626_CRABIT_CLKSRC_B)) { + /* Timer mode (ClkSrcB<1> == 1): */ + /* Indicate Timer mode. */ + setup |= S626_CLKSRC_TIMER << S626_STDBIT_CLKSRC; + /* Indicate multiplier is 1x. */ + setup |= S626_MULT_X1 << S626_STDBIT_CLKMULT; + /* Set ClkPol equal to Timer count direction (ClkSrcB<0>). */ + setup |= (cra >> (S626_CRABIT_CLKSRC_B - S626_STDBIT_CLKPOL)) & + S626_STDMSK_CLKPOL; + } else { + /* If Counter mode (ClkSrcB<1> == 0): */ + /* Indicate Timer mode. */ + setup |= S626_CLKSRC_COUNTER << S626_STDBIT_CLKSRC; + /* Clock multiplier is passed through. */ + setup |= (crb >> (S626_CRBBIT_CLKMULT_B - + S626_STDBIT_CLKMULT)) & S626_STDMSK_CLKMULT; + /* Clock polarity is passed through. */ + setup |= (crb << (S626_STDBIT_CLKPOL - S626_CRBBIT_CLKPOL_B)) & + S626_STDMSK_CLKPOL; + } + + /* 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. + */ +static void s626_set_mode_a(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t setup, + uint16_t disable_int_src) +{ + struct s626_private *devpriv = dev->private; + uint16_t cra; + uint16_t crb; + + /* Initialize CRA and CRB images. */ + /* Preload trigger is passed through. */ + cra = setup & S626_CRAMSK_LOADSRC_A; + /* IndexSrc is restricted to ENC_X or IndxPol. */ + cra |= (setup & S626_STDMSK_INDXSRC) >> + (S626_STDBIT_INDXSRC - (S626_CRABIT_INDXSRC_A + 1)); + + /* Reset any pending CounterA event captures. */ + crb = S626_CRBMSK_INTRESETCMD | S626_CRBMSK_INTRESET_A; + /* Clock enable is passed through. */ + crb |= (setup & S626_STDMSK_CLKENAB) << + (S626_CRBBIT_CLKENAB_A - S626_STDBIT_CLKENAB); + + /* Force IntSrc to Disabled if disable_int_src is asserted. */ + if (!disable_int_src) + cra |= (setup & S626_STDMSK_INTSRC) >> + (S626_STDBIT_INTSRC - S626_CRABIT_INTSRC_A); + + /* Populate all mode-dependent attributes of CRA & CRB images. */ + switch ((setup & S626_STDMSK_CLKSRC) >> S626_STDBIT_CLKSRC) { + case S626_CLKSRC_EXTENDER: /* Extender Mode: */ + /* Force to Timer mode (Extender valid only for B counters). */ + /* Fall through to case S626_CLKSRC_TIMER: */ + case S626_CLKSRC_TIMER: /* Timer Mode: */ + /* ClkSrcA<1> selects system clock */ + cra |= 2 << S626_CRABIT_CLKSRC_A; + /* Count direction (ClkSrcA<0>) obtained from ClkPol. */ + cra |= (setup & S626_STDMSK_CLKPOL) >> + (S626_STDBIT_CLKPOL - S626_CRABIT_CLKSRC_A); + /* ClkPolA behaves as always-on clock enable. */ + cra |= 1 << S626_CRABIT_CLKPOL_A; + /* ClkMult must be 1x. */ + cra |= S626_MULT_X1 << S626_CRABIT_CLKMULT_A; + break; + default: /* Counter Mode: */ + /* Select ENC_C and ENC_D as clock/direction inputs. */ + cra |= S626_CLKSRC_COUNTER; + /* Clock polarity is passed through. */ + cra |= (setup & S626_STDMSK_CLKPOL) << + (S626_CRABIT_CLKPOL_A - S626_STDBIT_CLKPOL); + /* Force multiplier to x1 if not legal, else pass through. */ + if ((setup & S626_STDMSK_CLKMULT) == + (S626_MULT_X0 << S626_STDBIT_CLKMULT)) + cra |= S626_MULT_X1 << S626_CRABIT_CLKMULT_A; + else + cra |= (setup & S626_STDMSK_CLKMULT) << + (S626_CRABIT_CLKMULT_A - S626_STDBIT_CLKMULT); + break; + } + + /* + * Force positive index polarity if IndxSrc is software-driven only, + * otherwise pass it through. + */ + if (~setup & S626_STDMSK_INDXSRC) + cra |= (setup & S626_STDMSK_INDXPOL) << + (S626_CRABIT_INDXPOL_A - S626_STDBIT_INDXPOL); + + /* + * If IntSrc has been forced to Disabled, update the MISC2 interrupt + * enable mask to indicate the counter interrupt is disabled. + */ + if (disable_int_src) + devpriv->counter_int_enabs &= ~k->my_event_bits[3]; + + /* + * While retaining CounterB and LatchSrc configurations, program the + * new counter operating mode. + */ + s626_debi_replace(dev, k->my_cra, + S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CLKSRC_B, cra); + s626_debi_replace(dev, k->my_crb, + ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_A), crb); +} + +static void s626_set_mode_b(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t setup, + uint16_t disable_int_src) +{ + struct s626_private *devpriv = dev->private; + uint16_t cra; + uint16_t crb; + + /* Initialize CRA and CRB images. */ + /* IndexSrc field is restricted to ENC_X or IndxPol. */ + cra = (setup & S626_STDMSK_INDXSRC) << + (S626_CRABIT_INDXSRC_B + 1 - S626_STDBIT_INDXSRC); + + /* Reset event captures and disable interrupts. */ + crb = S626_CRBMSK_INTRESETCMD | S626_CRBMSK_INTRESET_B; + /* Clock enable is passed through. */ + crb |= (setup & S626_STDMSK_CLKENAB) << + (S626_CRBBIT_CLKENAB_B - S626_STDBIT_CLKENAB); + /* Preload trigger source is passed through. */ + crb |= (setup & S626_STDMSK_LOADSRC) >> + (S626_STDBIT_LOADSRC - S626_CRBBIT_LOADSRC_B); + + /* Force IntSrc to Disabled if disable_int_src is asserted. */ + if (!disable_int_src) + crb |= (setup & S626_STDMSK_INTSRC) >> + (S626_STDBIT_INTSRC - S626_CRBBIT_INTSRC_B); + + /* Populate all mode-dependent attributes of CRA & CRB images. */ + switch ((setup & S626_STDMSK_CLKSRC) >> S626_STDBIT_CLKSRC) { + case S626_CLKSRC_TIMER: /* Timer Mode: */ + /* ClkSrcB<1> selects system clock */ + cra |= 2 << S626_CRABIT_CLKSRC_B; + /* with direction (ClkSrcB<0>) obtained from ClkPol. */ + cra |= (setup & S626_STDMSK_CLKPOL) << + (S626_CRABIT_CLKSRC_B - S626_STDBIT_CLKPOL); + /* ClkPolB behaves as always-on clock enable. */ + crb |= 1 << S626_CRBBIT_CLKPOL_B; + /* ClkMultB must be 1x. */ + crb |= S626_MULT_X1 << S626_CRBBIT_CLKMULT_B; + break; + case S626_CLKSRC_EXTENDER: /* Extender Mode: */ + /* ClkSrcB source is OverflowA (same as "timer") */ + cra |= 2 << S626_CRABIT_CLKSRC_B; + /* with direction obtained from ClkPol. */ + cra |= (setup & S626_STDMSK_CLKPOL) << + (S626_CRABIT_CLKSRC_B - S626_STDBIT_CLKPOL); + /* ClkPolB controls IndexB -- always set to active. */ + crb |= 1 << S626_CRBBIT_CLKPOL_B; + /* ClkMultB selects OverflowA as the clock source. */ + crb |= S626_MULT_X0 << S626_CRBBIT_CLKMULT_B; + break; + default: /* Counter Mode: */ + /* Select ENC_C and ENC_D as clock/direction inputs. */ + cra |= S626_CLKSRC_COUNTER << S626_CRABIT_CLKSRC_B; + /* ClkPol is passed through. */ + crb |= (setup & S626_STDMSK_CLKPOL) >> + (S626_STDBIT_CLKPOL - S626_CRBBIT_CLKPOL_B); + /* Force ClkMult to x1 if not legal, otherwise pass through. */ + if ((setup & S626_STDMSK_CLKMULT) == + (S626_MULT_X0 << S626_STDBIT_CLKMULT)) + crb |= S626_MULT_X1 << S626_CRBBIT_CLKMULT_B; + else + crb |= (setup & S626_STDMSK_CLKMULT) << + (S626_CRBBIT_CLKMULT_B - S626_STDBIT_CLKMULT); + break; + } + + /* + * Force positive index polarity if IndxSrc is software-driven only, + * otherwise pass it through. + */ + if (~setup & S626_STDMSK_INDXSRC) + crb |= (setup & S626_STDMSK_INDXPOL) >> + (S626_STDBIT_INDXPOL - S626_CRBBIT_INDXPOL_B); + + /* + * If IntSrc has been forced to Disabled, update the MISC2 interrupt + * enable mask to indicate the counter interrupt is disabled. + */ + if (disable_int_src) + devpriv->counter_int_enabs &= ~k->my_event_bits[3]; + + /* + * While retaining CounterA and LatchSrc configurations, program the + * new counter operating mode. + */ + s626_debi_replace(dev, k->my_cra, + ~(S626_CRAMSK_INDXSRC_B | S626_CRAMSK_CLKSRC_B), cra); + s626_debi_replace(dev, k->my_crb, + S626_CRBMSK_CLKENAB_A | S626_CRBMSK_LATCHSRC, crb); +} + +/* + * Return/set a counter's enable. enab: 0=always enabled, 1=enabled by index. + */ +static void s626_set_enable_a(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t enab) +{ + s626_debi_replace(dev, k->my_crb, + ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_A), + enab << S626_CRBBIT_CLKENAB_A); +} + +static void s626_set_enable_b(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t enab) +{ + s626_debi_replace(dev, k->my_crb, + ~(S626_CRBMSK_INTCTRL | S626_CRBMSK_CLKENAB_B), + enab << S626_CRBBIT_CLKENAB_B); +} + +static uint16_t s626_get_enable_a(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return (s626_debi_read(dev, k->my_crb) >> S626_CRBBIT_CLKENAB_A) & 1; +} + +static uint16_t s626_get_enable_b(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return (s626_debi_read(dev, k->my_crb) >> S626_CRBBIT_CLKENAB_B) & 1; +} + +#ifdef unused +static uint16_t s626_get_latch_source(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return (s626_debi_read(dev, k->my_crb) >> S626_CRBBIT_LATCHSRC) & 3; +} +#endif + +/* + * 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 s626_set_load_trig_a(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t trig) +{ + s626_debi_replace(dev, k->my_cra, ~S626_CRAMSK_LOADSRC_A, + trig << S626_CRABIT_LOADSRC_A); +} + +static void s626_set_load_trig_b(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t trig) +{ + s626_debi_replace(dev, k->my_crb, + ~(S626_CRBMSK_LOADSRC_B | S626_CRBMSK_INTCTRL), + trig << S626_CRBBIT_LOADSRC_B); +} + +static uint16_t s626_get_load_trig_a(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return (s626_debi_read(dev, k->my_cra) >> S626_CRABIT_LOADSRC_A) & 3; +} + +static uint16_t s626_get_load_trig_b(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return (s626_debi_read(dev, k->my_crb) >> S626_CRBBIT_LOADSRC_B) & 3; +} + +/* + * Return/set counter interrupt source and clear any captured + * index/overflow events. int_source: 0=Disabled, 1=OverflowOnly, + * 2=IndexOnly, 3=IndexAndOverflow. + */ +static void s626_set_int_src_a(struct comedi_device *dev, + const struct s626_enc_info *k, + uint16_t int_source) +{ + struct s626_private *devpriv = dev->private; + + /* Reset any pending counter overflow or index captures. */ + s626_debi_replace(dev, k->my_crb, ~S626_CRBMSK_INTCTRL, + S626_CRBMSK_INTRESETCMD | S626_CRBMSK_INTRESET_A); + + /* Program counter interrupt source. */ + s626_debi_replace(dev, k->my_cra, ~S626_CRAMSK_INTSRC_A, + int_source << S626_CRABIT_INTSRC_A); + + /* Update MISC2 interrupt enable mask. */ + devpriv->counter_int_enabs = + (devpriv->counter_int_enabs & ~k->my_event_bits[3]) | + k->my_event_bits[int_source]; +} + +static void s626_set_int_src_b(struct comedi_device *dev, + const struct s626_enc_info *k, + uint16_t int_source) +{ + struct s626_private *devpriv = dev->private; + uint16_t crb; + + /* Cache writeable CRB register image. */ + crb = s626_debi_read(dev, k->my_crb) & ~S626_CRBMSK_INTCTRL; + + /* Reset any pending counter overflow or index captures. */ + s626_debi_write(dev, k->my_crb, (crb | S626_CRBMSK_INTRESETCMD | + S626_CRBMSK_INTRESET_B)); + + /* Program counter interrupt source. */ + s626_debi_write(dev, k->my_crb, + ((crb & ~S626_CRBMSK_INTSRC_B) | + (int_source << S626_CRBBIT_INTSRC_B))); + + /* Update MISC2 interrupt enable mask. */ + devpriv->counter_int_enabs = + (devpriv->counter_int_enabs & ~k->my_event_bits[3]) | + k->my_event_bits[int_source]; +} + +static uint16_t s626_get_int_src_a(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return (s626_debi_read(dev, k->my_cra) >> S626_CRABIT_INTSRC_A) & 3; +} + +static uint16_t s626_get_int_src_b(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return (s626_debi_read(dev, k->my_crb) >> S626_CRBBIT_INTSRC_B) & 3; +} + +#ifdef unused +/* + * Return/set the clock multiplier. + */ +static void s626_set_clk_mult(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t value) +{ + k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_CLKMULT) | + (value << S626_STDBIT_CLKMULT)), false); +} + +static uint16_t s626_get_clk_mult(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return (k->get_mode(dev, k) >> S626_STDBIT_CLKMULT) & 3; +} + +/* + * Return/set the clock polarity. + */ +static void s626_set_clk_pol(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t value) +{ + k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_CLKPOL) | + (value << S626_STDBIT_CLKPOL)), false); +} + +static uint16_t s626_get_clk_pol(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return (k->get_mode(dev, k) >> S626_STDBIT_CLKPOL) & 1; +} + +/* + * Return/set the clock source. + */ +static void s626_set_clk_src(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t value) +{ + k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_CLKSRC) | + (value << S626_STDBIT_CLKSRC)), false); +} + +static uint16_t s626_get_clk_src(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return (k->get_mode(dev, k) >> S626_STDBIT_CLKSRC) & 3; +} + +/* + * Return/set the index polarity. + */ +static void s626_set_index_pol(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t value) +{ + k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_INDXPOL) | + ((value != 0) << S626_STDBIT_INDXPOL)), false); +} + +static uint16_t s626_get_index_pol(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return (k->get_mode(dev, k) >> S626_STDBIT_INDXPOL) & 1; +} - return tempdata; +/* + * Return/set the index source. + */ +static void s626_set_index_src(struct comedi_device *dev, + const struct s626_enc_info *k, uint16_t value) +{ + k->set_mode(dev, k, ((k->get_mode(dev, k) & ~S626_STDMSK_INDXSRC) | + ((value != 0) << S626_STDBIT_INDXSRC)), false); +} + +static uint16_t s626_get_index_src(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + return (k->get_mode(dev, k) >> S626_STDBIT_INDXSRC) & 1; +} +#endif + +/* + * Generate an index pulse. + */ +static void s626_pulse_index_a(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + uint16_t cra; + + cra = s626_debi_read(dev, k->my_cra); + /* Pulse index. */ + s626_debi_write(dev, k->my_cra, (cra ^ S626_CRAMSK_INDXPOL_A)); + s626_debi_write(dev, k->my_cra, cra); } -/* static unsigned int s626_uint_to_reg(struct comedi_subdevice *s, int data){ */ -/* return 0; */ -/* } */ +static void s626_pulse_index_b(struct comedi_device *dev, + const struct s626_enc_info *k) +{ + uint16_t crb; + + crb = s626_debi_read(dev, k->my_crb) & ~S626_CRBMSK_INTCTRL; + /* Pulse index. */ + s626_debi_write(dev, k->my_crb, (crb ^ S626_CRBMSK_INDXPOL_B)); + s626_debi_write(dev, k->my_crb, crb); +} + +static const struct s626_enc_info s626_enc_chan_info[] = { + { + .get_enable = s626_get_enable_a, + .get_int_src = s626_get_int_src_a, + .get_load_trig = s626_get_load_trig_a, + .get_mode = s626_get_mode_a, + .pulse_index = s626_pulse_index_a, + .set_enable = s626_set_enable_a, + .set_int_src = s626_set_int_src_a, + .set_load_trig = s626_set_load_trig_a, + .set_mode = s626_set_mode_a, + .reset_cap_flags = s626_reset_cap_flags_a, + .my_cra = S626_LP_CR0A, + .my_crb = S626_LP_CR0B, + .my_latch_lsw = S626_LP_CNTR0ALSW, + .my_event_bits = S626_EVBITS(0), + }, { + .get_enable = s626_get_enable_a, + .get_int_src = s626_get_int_src_a, + .get_load_trig = s626_get_load_trig_a, + .get_mode = s626_get_mode_a, + .pulse_index = s626_pulse_index_a, + .set_enable = s626_set_enable_a, + .set_int_src = s626_set_int_src_a, + .set_load_trig = s626_set_load_trig_a, + .set_mode = s626_set_mode_a, + .reset_cap_flags = s626_reset_cap_flags_a, + .my_cra = S626_LP_CR1A, + .my_crb = S626_LP_CR1B, + .my_latch_lsw = S626_LP_CNTR1ALSW, + .my_event_bits = S626_EVBITS(1), + }, { + .get_enable = s626_get_enable_a, + .get_int_src = s626_get_int_src_a, + .get_load_trig = s626_get_load_trig_a, + .get_mode = s626_get_mode_a, + .pulse_index = s626_pulse_index_a, + .set_enable = s626_set_enable_a, + .set_int_src = s626_set_int_src_a, + .set_load_trig = s626_set_load_trig_a, + .set_mode = s626_set_mode_a, + .reset_cap_flags = s626_reset_cap_flags_a, + .my_cra = S626_LP_CR2A, + .my_crb = S626_LP_CR2B, + .my_latch_lsw = S626_LP_CNTR2ALSW, + .my_event_bits = S626_EVBITS(2), + }, { + .get_enable = s626_get_enable_b, + .get_int_src = s626_get_int_src_b, + .get_load_trig = s626_get_load_trig_b, + .get_mode = s626_get_mode_b, + .pulse_index = s626_pulse_index_b, + .set_enable = s626_set_enable_b, + .set_int_src = s626_set_int_src_b, + .set_load_trig = s626_set_load_trig_b, + .set_mode = s626_set_mode_b, + .reset_cap_flags = s626_reset_cap_flags_b, + .my_cra = S626_LP_CR0A, + .my_crb = S626_LP_CR0B, + .my_latch_lsw = S626_LP_CNTR0BLSW, + .my_event_bits = S626_EVBITS(3), + }, { + .get_enable = s626_get_enable_b, + .get_int_src = s626_get_int_src_b, + .get_load_trig = s626_get_load_trig_b, + .get_mode = s626_get_mode_b, + .pulse_index = s626_pulse_index_b, + .set_enable = s626_set_enable_b, + .set_int_src = s626_set_int_src_b, + .set_load_trig = s626_set_load_trig_b, + .set_mode = s626_set_mode_b, + .reset_cap_flags = s626_reset_cap_flags_b, + .my_cra = S626_LP_CR1A, + .my_crb = S626_LP_CR1B, + .my_latch_lsw = S626_LP_CNTR1BLSW, + .my_event_bits = S626_EVBITS(4), + }, { + .get_enable = s626_get_enable_b, + .get_int_src = s626_get_int_src_b, + .get_load_trig = s626_get_load_trig_b, + .get_mode = s626_get_mode_b, + .pulse_index = s626_pulse_index_b, + .set_enable = s626_set_enable_b, + .set_int_src = s626_set_int_src_b, + .set_load_trig = s626_set_load_trig_b, + .set_mode = s626_set_mode_b, + .reset_cap_flags = s626_reset_cap_flags_b, + .my_cra = S626_LP_CR2A, + .my_crb = S626_LP_CR2B, + .my_latch_lsw = S626_LP_CNTR2BLSW, + .my_event_bits = S626_EVBITS(5), + }, +}; + +static unsigned int s626_ai_reg_to_uint(unsigned int data) +{ + return ((data >> 18) & 0x3fff) ^ 0x2000; +} static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan) { @@ -629,19 +1341,19 @@ static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan) unsigned int status; /* set channel to capture positive edge */ - status = DEBIread(dev, LP_RDEDGSEL(group)); - DEBIwrite(dev, LP_WREDGSEL(group), mask | status); + status = s626_debi_read(dev, S626_LP_RDEDGSEL(group)); + s626_debi_write(dev, S626_LP_WREDGSEL(group), mask | status); /* enable interrupt on selected channel */ - status = DEBIread(dev, LP_RDINTSEL(group)); - DEBIwrite(dev, LP_WRINTSEL(group), mask | status); + status = s626_debi_read(dev, S626_LP_RDINTSEL(group)); + s626_debi_write(dev, S626_LP_WRINTSEL(group), mask | status); /* enable edge capture write command */ - DEBIwrite(dev, LP_MISC1, MISC1_EDCAP); + s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_EDCAP); /* enable edge capture on selected channel */ - status = DEBIread(dev, LP_RDCAPSEL(group)); - DEBIwrite(dev, LP_WRCAPSEL(group), mask | status); + status = s626_debi_read(dev, S626_LP_RDCAPSEL(group)); + s626_debi_write(dev, S626_LP_WRCAPSEL(group), mask | status); return 0; } @@ -650,10 +1362,10 @@ static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int group, unsigned int mask) { /* disable edge capture write command */ - DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); + s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP); /* enable edge capture on selected channel */ - DEBIwrite(dev, LP_WRCAPSEL(group), mask); + s626_debi_write(dev, S626_LP_WRCAPSEL(group), mask); return 0; } @@ -663,17 +1375,17 @@ static int s626_dio_clear_irq(struct comedi_device *dev) unsigned int group; /* disable edge capture write command */ - DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); + s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP); /* clear all dio pending events and interrupt */ for (group = 0; group < S626_DIO_BANKS; group++) - DEBIwrite(dev, LP_WRCAPSEL(group), 0xffff); + s626_debi_write(dev, S626_LP_WRCAPSEL(group), 0xffff); return 0; } -static void handle_dio_interrupt(struct comedi_device *dev, - uint16_t irqbit, uint8_t group) +static void s626_handle_dio_interrupt(struct comedi_device *dev, + uint16_t irqbit, uint8_t group) { struct s626_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; @@ -686,7 +1398,7 @@ static void handle_dio_interrupt(struct comedi_device *dev, if ((irqbit >> (cmd->start_arg - (16 * group))) == 1 && cmd->start_src == TRIG_EXT) { /* Start executing the RPS program */ - s626_mc_enable(dev, MC1_ERPS1, P_MC1); + s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1); if (cmd->scan_begin_src == TRIG_EXT) s626_dio_set_irq(dev, cmd->scan_begin_arg); @@ -694,7 +1406,7 @@ static void handle_dio_interrupt(struct comedi_device *dev, if ((irqbit >> (cmd->scan_begin_arg - (16 * group))) == 1 && cmd->scan_begin_src == TRIG_EXT) { /* Trigger ADC scan loop start */ - s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); + s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); if (cmd->convert_src == TRIG_EXT) { devpriv->ai_convert_count = cmd->chanlist_len; @@ -703,16 +1415,17 @@ static void handle_dio_interrupt(struct comedi_device *dev, } if (cmd->convert_src == TRIG_TIMER) { - struct enc_private *k = &encpriv[5]; + const struct s626_enc_info *k = + &s626_enc_chan_info[5]; devpriv->ai_convert_count = cmd->chanlist_len; - k->SetEnable(dev, k, CLKENAB_ALWAYS); + k->set_enable(dev, k, S626_CLKENAB_ALWAYS); } } if ((irqbit >> (cmd->convert_arg - (16 * group))) == 1 && cmd->convert_src == TRIG_EXT) { /* Trigger ADC scan loop start */ - s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); + s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); devpriv->ai_convert_count--; if (devpriv->ai_convert_count > 0) @@ -721,7 +1434,7 @@ static void handle_dio_interrupt(struct comedi_device *dev, } } -static void check_dio_interrupts(struct comedi_device *dev) +static void s626_check_dio_interrupts(struct comedi_device *dev) { uint16_t irqbit; uint8_t group; @@ -729,90 +1442,91 @@ static void check_dio_interrupts(struct comedi_device *dev) for (group = 0; group < S626_DIO_BANKS; group++) { irqbit = 0; /* read interrupt type */ - irqbit = DEBIread(dev, LP_RDCAPFLG(group)); + irqbit = s626_debi_read(dev, S626_LP_RDCAPFLG(group)); /* check if interrupt is generated from dio channels */ if (irqbit) { - handle_dio_interrupt(dev, irqbit, group); + s626_handle_dio_interrupt(dev, irqbit, group); return; } } } -static void check_counter_interrupts(struct comedi_device *dev) +static void s626_check_counter_interrupts(struct comedi_device *dev) { struct s626_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; - struct enc_private *k; + const struct s626_enc_info *k; uint16_t irqbit; /* read interrupt type */ - irqbit = DEBIread(dev, LP_RDMISC2); + irqbit = s626_debi_read(dev, S626_LP_RDMISC2); /* check interrupt on counters */ - if (irqbit & IRQ_COINT1A) { - k = &encpriv[0]; + if (irqbit & S626_IRQ_COINT1A) { + k = &s626_enc_chan_info[0]; /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + k->reset_cap_flags(dev, k); } - if (irqbit & IRQ_COINT2A) { - k = &encpriv[1]; + if (irqbit & S626_IRQ_COINT2A) { + k = &s626_enc_chan_info[1]; /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + k->reset_cap_flags(dev, k); } - if (irqbit & IRQ_COINT3A) { - k = &encpriv[2]; + if (irqbit & S626_IRQ_COINT3A) { + k = &s626_enc_chan_info[2]; /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + k->reset_cap_flags(dev, k); } - if (irqbit & IRQ_COINT1B) { - k = &encpriv[3]; + if (irqbit & S626_IRQ_COINT1B) { + k = &s626_enc_chan_info[3]; /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + k->reset_cap_flags(dev, k); } - if (irqbit & IRQ_COINT2B) { - k = &encpriv[4]; + if (irqbit & S626_IRQ_COINT2B) { + k = &s626_enc_chan_info[4]; /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + k->reset_cap_flags(dev, k); if (devpriv->ai_convert_count > 0) { devpriv->ai_convert_count--; if (devpriv->ai_convert_count == 0) - k->SetEnable(dev, k, CLKENAB_INDEX); + k->set_enable(dev, k, S626_CLKENAB_INDEX); if (cmd->convert_src == TRIG_TIMER) { /* Trigger ADC scan loop start */ - s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); + s626_mc_enable(dev, S626_MC2_ADC_RPS, + S626_P_MC2); } } } - if (irqbit & IRQ_COINT3B) { - k = &encpriv[5]; + if (irqbit & S626_IRQ_COINT3B) { + k = &s626_enc_chan_info[5]; /* clear interrupt capture flag */ - k->ResetCapFlags(dev, k); + k->reset_cap_flags(dev, k); if (cmd->scan_begin_src == TRIG_TIMER) { /* Trigger ADC scan loop start */ - s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); + s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); } if (cmd->convert_src == TRIG_TIMER) { - k = &encpriv[4]; + k = &s626_enc_chan_info[4]; devpriv->ai_convert_count = cmd->chanlist_len; - k->SetEnable(dev, k, CLKENAB_ALWAYS); + k->set_enable(dev, k, S626_CLKENAB_ALWAYS); } } } -static bool handle_eos_interrupt(struct comedi_device *dev) +static bool s626_handle_eos_interrupt(struct comedi_device *dev) { struct s626_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; @@ -823,19 +1537,19 @@ static bool handle_eos_interrupt(struct comedi_device *dev) * first uint16_t in the buffer because it contains junk data * from the final ADC of the previous poll list scan. */ - int32_t *readaddr = (int32_t *)devpriv->ANABuf.LogicalBase + 1; + uint32_t *readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1; bool finished = false; int i; /* get the data and hand it over to comedi */ for (i = 0; i < cmd->chanlist_len; i++) { - short tempdata; + unsigned short tempdata; /* * Convert ADC data to 16-bit integer values and copy * to application buffer. */ - tempdata = s626_ai_reg_to_uint((int)*readaddr); + tempdata = s626_ai_reg_to_uint(*readaddr); readaddr++; /* put data into read buffer */ @@ -846,13 +1560,13 @@ static bool handle_eos_interrupt(struct comedi_device *dev) /* end of scan occurs */ async->events |= COMEDI_CB_EOS; - if (!devpriv->ai_continous) + if (!devpriv->ai_continuous) devpriv->ai_sample_count--; if (devpriv->ai_sample_count <= 0) { devpriv->ai_cmd_running = 0; /* Stop RPS program */ - s626_mc_disable(dev, MC1_ERPS1, P_MC1); + s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1); /* send end of acquisition */ async->events |= COMEDI_CB_EOA; @@ -879,229 +1593,238 @@ static irqreturn_t s626_irq_handler(int irq, void *d) if (!dev->attached) return IRQ_NONE; - /* lock to avoid race with comedi_poll */ + /* lock to avoid race with comedi_poll */ spin_lock_irqsave(&dev->spinlock, flags); /* save interrupt enable register state */ - irqstatus = readl(devpriv->mmio + P_IER); + irqstatus = readl(devpriv->mmio + S626_P_IER); /* read interrupt type */ - irqtype = readl(devpriv->mmio + P_ISR); + irqtype = readl(devpriv->mmio + S626_P_ISR); /* disable master interrupt */ - writel(0, devpriv->mmio + P_IER); + writel(0, devpriv->mmio + S626_P_IER); /* clear interrupt */ - writel(irqtype, devpriv->mmio + P_ISR); + writel(irqtype, devpriv->mmio + S626_P_ISR); switch (irqtype) { - case IRQ_RPS1: /* end_of_scan occurs */ - if (handle_eos_interrupt(dev)) + case S626_IRQ_RPS1: /* end_of_scan occurs */ + if (s626_handle_eos_interrupt(dev)) irqstatus = 0; break; - case IRQ_GPIO3: /* check dio and conter interrupt */ + case S626_IRQ_GPIO3: /* check dio and counter interrupt */ /* s626_dio_clear_irq(dev); */ - check_dio_interrupts(dev); - check_counter_interrupts(dev); + s626_check_dio_interrupts(dev); + s626_check_counter_interrupts(dev); break; } /* enable interrupt */ - writel(irqstatus, devpriv->mmio + P_IER); + writel(irqstatus, devpriv->mmio + S626_P_IER); spin_unlock_irqrestore(&dev->spinlock, flags); return IRQ_HANDLED; } /* - * this functions build the RPS program for hardware driven acquistion + * This function builds the RPS program for hardware driven acquisition. */ -static void ResetADC(struct comedi_device *dev, uint8_t *ppl) +static void s626_reset_adc(struct comedi_device *dev, uint8_t *ppl) { struct s626_private *devpriv = dev->private; - register uint32_t *pRPS; - uint32_t JmpAdrs; + uint32_t *rps; + uint32_t jmp_adrs; uint16_t i; uint16_t n; - uint32_t LocalPPL; - struct comedi_cmd *cmd = &(dev->subdevices->async->cmd); + uint32_t local_ppl; + struct comedi_cmd *cmd = &dev->subdevices->async->cmd; /* Stop RPS program in case it is currently running */ - s626_mc_disable(dev, MC1_ERPS1, P_MC1); + s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1); - /* Set starting logical address to write RPS commands. */ - pRPS = (uint32_t *) devpriv->RPSBuf.LogicalBase; + /* Set starting logical address to write RPS commands. */ + rps = (uint32_t *)devpriv->rps_buf.logical_base; /* Initialize RPS instruction pointer */ - writel((uint32_t)devpriv->RPSBuf.PhysicalBase, - devpriv->mmio + P_RPSADDR1); - - /* Construct RPS program in RPSBuf DMA buffer */ + writel((uint32_t)devpriv->rps_buf.physical_base, + devpriv->mmio + S626_P_RPSADDR1); + /* Construct RPS program in rps_buf DMA buffer */ if (cmd != NULL && cmd->scan_begin_src != TRIG_FOLLOW) { - /* Wait for Start trigger. */ - *pRPS++ = RPS_PAUSE | RPS_SIGADC; - *pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC; + /* Wait for Start trigger. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_SIGADC; + *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_SIGADC; } - /* SAA7146 BUG WORKAROUND Do a dummy DEBI Write. This is necessary + /* + * 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. */ + *rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2); + *rps++ = S626_DEBI_CMD_WRWORD | S626_LP_GSEL; + *rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2); + /* Write DEBI immediate data to shadow RAM: */ + *rps++ = S626_GSEL_BIPOLAR5V; /* arbitrary immediate data value. */ + *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI; + /* Reset "shadow RAM uploaded" flag. */ + /* Invoke shadow RAM upload. */ + *rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI; + /* Wait for shadow upload to finish. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_DEBI; - *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 + /* + * 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. + * forgot to set the S626_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 + for (devpriv->adc_items = 0; devpriv->adc_items < 16; + devpriv->adc_items++) { + /* + * 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. */ - *pRPS++ = DEBI_CMD_WRWORD | LP_GSEL; - *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. */ - - /* 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++ = 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. */ - - /* 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. + local_ppl = (*ppl << 8) | (*ppl & 0x10 ? S626_GSEL_BIPOLAR5V : + S626_GSEL_BIPOLAR10V); + + /* Switch ADC analog gain. */ + /* Write DEBI command and address to shadow RAM. */ + *rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2); + *rps++ = S626_DEBI_CMD_WRWORD | S626_LP_GSEL; + /* Write DEBI immediate data to shadow RAM. */ + *rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2); + *rps++ = local_ppl; + /* Reset "shadow RAM uploaded" flag. */ + *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI; + /* Invoke shadow RAM upload. */ + *rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI; + /* Wait for shadow upload to finish. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_DEBI; + /* Select ADC analog input channel. */ + *rps++ = S626_RPS_LDREG | (S626_P_DEBICMD >> 2); + /* Write DEBI command and address to shadow RAM. */ + *rps++ = S626_DEBI_CMD_WRWORD | S626_LP_ISEL; + *rps++ = S626_RPS_LDREG | (S626_P_DEBIAD >> 2); + /* Write DEBI immediate data to shadow RAM. */ + *rps++ = local_ppl; + /* Reset "shadow RAM uploaded" flag. */ + *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_DEBI; + /* Invoke shadow RAM upload. */ + *rps++ = S626_RPS_UPLOAD | S626_RPS_DEBI; + /* Wait for shadow upload to finish. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_DEBI; + + /* + * Delay at least 10 microseconds for analog input settling. + * Instead of padding with NOPs, we use S626_RPS_JUMP + * instructions here; this allows us to produce a longer delay + * than is possible with NOPs because each S626_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. */ - *pRPS++ = JmpAdrs; + jmp_adrs = + (uint32_t)devpriv->rps_buf.physical_base + + (uint32_t)((unsigned long)rps - + (unsigned long)devpriv-> + rps_buf.logical_base); + for (i = 0; i < (10 * S626_RPSCLK_PER_US / 2); i++) { + jmp_adrs += 8; /* Repeat to implement time delay: */ + /* Jump to next RPS instruction. */ + *rps++ = S626_RPS_JUMP; + *rps++ = jmp_adrs; } if (cmd != NULL && cmd->convert_src != TRIG_NOW) { - /* Wait for Start trigger. */ - *pRPS++ = RPS_PAUSE | RPS_SIGADC; - *pRPS++ = RPS_CLRSIGNAL | RPS_SIGADC; + /* Wait for Start trigger. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_SIGADC; + *rps++ = S626_RPS_CLRSIGNAL | S626_RPS_SIGADC; } - /* 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. */ - *pRPS++ = GPIO_BASE | GPIO1_HI; - - /* Wait for ADC to complete (GPIO2 is asserted high when ADC not + /* Start ADC by pulsing GPIO1. */ + /* Begin ADC Start pulse. */ + *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2); + *rps++ = S626_GPIO_BASE | S626_GPIO1_LO; + *rps++ = S626_RPS_NOP; + /* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */ + /* End ADC Start pulse. */ + *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2); + *rps++ = S626_GPIO_BASE | S626_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. */ - - /* 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 (*ppl++ & EOPL) { - devpriv->AdcItems++; /* Adjust poll list item count. */ - break; /* Exit poll list processing loop. */ + /* Wait for ADC done. */ + *rps++ = S626_RPS_PAUSE | S626_RPS_GPIO2; + + /* Transfer ADC data from FB BUFFER 1 register to DMA buffer. */ + *rps++ = S626_RPS_STREG | + (S626_BUGFIX_STREG(S626_P_FB_BUFFER1) >> 2); + *rps++ = (uint32_t)devpriv->ana_buf.physical_base + + (devpriv->adc_items << 2); + + /* + * If this slot's EndOfPollList flag is set, all channels have + * now been processed. + */ + if (*ppl++ & S626_EOPL) { + devpriv->adc_items++; /* Adjust poll list item count. */ + break; /* Exit poll list processing loop. */ } } - /* VERSION 2.01 CHANGE: DELAY CHANGED FROM 250NS to 2US. Allow the + /* + * 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; + for (n = 0; n < (2 * S626_RPSCLK_PER_US); n++) + *rps++ = S626_RPS_NOP; - /* Start a dummy conversion to cause the data from the last + /* + * 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; + /* Begin ADC Start pulse. */ + *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2); + *rps++ = S626_GPIO_BASE | S626_GPIO1_LO; + *rps++ = S626_RPS_NOP; /* VERSION 2.03 CHANGE: STRETCH OUT ADC START PULSE. */ - *pRPS++ = RPS_LDREG | (P_GPIO >> 2); /* End ADC Start pulse. */ - *pRPS++ = GPIO_BASE | GPIO1_HI; + *rps++ = S626_RPS_LDREG | (S626_P_GPIO >> 2); /* End ADC Start pulse. */ + *rps++ = S626_GPIO_BASE | S626_GPIO1_HI; - /* Wait for the data from the last conversion of interest to arrive + /* + * 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. */ + *rps++ = S626_RPS_PAUSE | S626_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); /* */ - *pRPS++ = - (uint32_t) devpriv->ANABuf.PhysicalBase + (devpriv->AdcItems << 2); + /* Transfer final ADC data from FB BUFFER 1 register to DMA buffer. */ + *rps++ = S626_RPS_STREG | (S626_BUGFIX_STREG(S626_P_FB_BUFFER1) >> 2); + *rps++ = (uint32_t)devpriv->ana_buf.physical_base + + (devpriv->adc_items << 2); - /* Indicate ADC scan loop is finished. */ - /* *pRPS++= RPS_CLRSIGNAL | RPS_SIGADC ; // Signal ReadADC() that scan is done. */ + /* Indicate ADC scan loop is finished. */ + /* Signal ReadADC() that scan is done. */ + /* *rps++= S626_RPS_CLRSIGNAL | S626_RPS_SIGADC; */ /* invoke interrupt */ - if (devpriv->ai_cmd_running == 1) { - *pRPS++ = RPS_IRQ; - } - /* Restart RPS program at its beginning. */ - *pRPS++ = RPS_JUMP; /* Branch to start of RPS program. */ - *pRPS++ = (uint32_t) devpriv->RPSBuf.PhysicalBase; + if (devpriv->ai_cmd_running == 1) + *rps++ = S626_RPS_IRQ; + + /* Restart RPS program at its beginning. */ + *rps++ = S626_RPS_JUMP; /* Branch to start of RPS program. */ + *rps++ = (uint32_t)devpriv->rps_buf.physical_base; - /* End of RPS program build */ + /* End of RPS program build */ } #ifdef unused_code @@ -1111,14 +1834,14 @@ static int s626_ai_rinsn(struct comedi_device *dev, unsigned int *data) { struct s626_private *devpriv = dev->private; - register uint8_t i; - register int32_t *readaddr; + uint8_t i; + int32_t *readaddr; /* Trigger ADC scan loop start */ - s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); + s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); /* Wait until ADC scan loop is finished (RPS Signal 0 reset) */ - while (s626_mc_test(dev, MC2_ADC_RPS, P_MC2)) + while (s626_mc_test(dev, S626_MC2_ADC_RPS, S626_P_MC2)) ; /* @@ -1126,13 +1849,13 @@ static int s626_ai_rinsn(struct comedi_device *dev, * 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; + readaddr = (uint32_t *)devpriv->ana_buf.logical_base + 1; /* * Convert ADC data to 16-bit integer values and * copy to application buffer. */ - for (i = 0; i < devpriv->AdcItems; i++) { + for (i = 0; i < devpriv->adc_items; i++) { *data = s626_ai_reg_to_uint(*readaddr++); data++; } @@ -1148,55 +1871,61 @@ static int s626_ai_insn_read(struct comedi_device *dev, struct s626_private *devpriv = dev->private; uint16_t chan = CR_CHAN(insn->chanspec); uint16_t range = CR_RANGE(insn->chanspec); - uint16_t AdcSpec = 0; - uint32_t GpioImage; - int tmp; + uint16_t adc_spec = 0; + uint32_t gpio_image; + uint32_t tmp; int n; - /* Convert application's ADC specification into form + /* + * Convert application's ADC specification into form * appropriate for register programming. */ if (range == 0) - AdcSpec = (chan << 8) | (GSEL_BIPOLAR5V); + adc_spec = (chan << 8) | (S626_GSEL_BIPOLAR5V); else - AdcSpec = (chan << 8) | (GSEL_BIPOLAR10V); + adc_spec = (chan << 8) | (S626_GSEL_BIPOLAR10V); - /* Switch ADC analog gain. */ - DEBIwrite(dev, LP_GSEL, AdcSpec); /* Set gain. */ + /* Switch ADC analog gain. */ + s626_debi_write(dev, S626_LP_GSEL, adc_spec); /* Set gain. */ - /* Select ADC analog input channel. */ - DEBIwrite(dev, LP_ISEL, AdcSpec); /* Select channel. */ + /* Select ADC analog input channel. */ + s626_debi_write(dev, S626_LP_ISEL, adc_spec); /* Select channel. */ for (n = 0; n < insn->n; n++) { - - /* Delay 10 microseconds for analog input settling. */ + /* Delay 10 microseconds for analog input settling. */ udelay(10); /* Start ADC by pulsing GPIO1 low */ - GpioImage = readl(devpriv->mmio + P_GPIO); + gpio_image = readl(devpriv->mmio + S626_P_GPIO); /* Assert ADC Start command */ - writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, + devpriv->mmio + S626_P_GPIO); /* and stretch it out */ - writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); - writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, + devpriv->mmio + S626_P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, + devpriv->mmio + S626_P_GPIO); /* Negate ADC Start command */ - writel(GpioImage | GPIO1_HI, devpriv->mmio + P_GPIO); + writel(gpio_image | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); - /* 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 (!(readl(devpriv->mmio + P_PSR) & PSR_GPIO2)) + while (!(readl(devpriv->mmio + S626_P_PSR) & S626_PSR_GPIO2)) ; /* Fetch ADC data */ if (n != 0) { - tmp = readl(devpriv->mmio + P_FB_BUFFER1); + tmp = readl(devpriv->mmio + S626_P_FB_BUFFER1); data[n - 1] = s626_ai_reg_to_uint(tmp); } - /* Allow the ADC to stabilize for 4 microseconds before + /* + * 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 @@ -1207,28 +1936,30 @@ static int s626_ai_insn_read(struct comedi_device *dev, udelay(4); } - /* Start a dummy conversion to cause the data from the - * previous conversion to be shifted in. */ - GpioImage = readl(devpriv->mmio + P_GPIO); + /* + * Start a dummy conversion to cause the data from the + * previous conversion to be shifted in. + */ + gpio_image = readl(devpriv->mmio + S626_P_GPIO); /* Assert ADC Start command */ - writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); /* and stretch it out */ - writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); - writel(GpioImage & ~GPIO1_HI, devpriv->mmio + P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); + writel(gpio_image & ~S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); /* Negate ADC Start command */ - writel(GpioImage | GPIO1_HI, devpriv->mmio + P_GPIO); + writel(gpio_image | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); - /* 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 (!(readl(devpriv->mmio + P_PSR) & PSR_GPIO2)) + while (!(readl(devpriv->mmio + S626_P_PSR) & S626_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 */ if (n != 0) { - tmp = readl(devpriv->mmio + P_FB_BUFFER1); + tmp = readl(devpriv->mmio + S626_P_FB_BUFFER1); data[n - 1] = s626_ai_reg_to_uint(tmp); } @@ -1237,17 +1968,16 @@ static int s626_ai_insn_read(struct comedi_device *dev, static int s626_ai_load_polllist(uint8_t *ppl, struct comedi_cmd *cmd) { - int n; for (n = 0; n < cmd->chanlist_len; n++) { - if (CR_RANGE((cmd->chanlist)[n]) == 0) - ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_5V); + if (CR_RANGE(cmd->chanlist[n]) == 0) + ppl[n] = CR_CHAN(cmd->chanlist[n]) | S626_RANGE_5V; else - ppl[n] = (CR_CHAN((cmd->chanlist)[n])) | (RANGE_10V); + ppl[n] = CR_CHAN(cmd->chanlist[n]) | S626_RANGE_10V; } if (n != 0) - ppl[n - 1] |= EOPL; + ppl[n - 1] |= S626_EOPL; return n; } @@ -1259,18 +1989,20 @@ static int s626_ai_inttrig(struct comedi_device *dev, return -EINVAL; /* Start executing the RPS program */ - s626_mc_enable(dev, MC1_ERPS1, P_MC1); + s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1); s->async->inttrig = NULL; return 1; } -/* This function doesn't require a particular form, this is just what +/* + * 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. */ + * that the device will use. + */ static int s626_ns_to_timer(int *nanosec, int round_mode) { int divider, base; @@ -1294,68 +2026,76 @@ static int s626_ns_to_timer(int *nanosec, int round_mode) return divider - 1; } -static void s626_timer_load(struct comedi_device *dev, struct enc_private *k, - int tick) +static void s626_timer_load(struct comedi_device *dev, + const struct s626_enc_info *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. */ - (CLKENAB_INDEX << BF_CLKENAB); - uint16_t valueSrclatch = LATCHSRC_A_INDXA; - /* uint16_t enab=CLKENAB_ALWAYS; */ + uint16_t setup = + /* Preload upon index. */ + (S626_LOADSRC_INDX << S626_BF_LOADSRC) | + /* Disable hardware index. */ + (S626_INDXSRC_SOFT << S626_BF_INDXSRC) | + /* Operating mode is Timer. */ + (S626_CLKSRC_TIMER << S626_BF_CLKSRC) | + /* Active high clock. */ + (S626_CLKPOL_POS << S626_BF_CLKPOL) | + /* Count direction is Down. */ + (S626_CNTDIR_DOWN << S626_BF_CLKPOL) | + /* Clock multiplier is 1x. */ + (S626_CLKMULT_1X << S626_BF_CLKMULT) | + (S626_CLKENAB_INDEX << S626_BF_CLKENAB); + uint16_t value_latchsrc = S626_LATCHSRC_A_INDXA; + /* uint16_t enab = S626_CLKENAB_ALWAYS; */ - k->SetMode(dev, k, Setup, FALSE); + k->set_mode(dev, k, setup, false); - /* Set the preload register */ - Preload(dev, k, tick); + /* Set the preload register */ + s626_preload(dev, k, tick); - /* Software index pulse forces the preload register to load */ - /* into the counter */ - k->SetLoadTrig(dev, k, 0); - k->PulseIndex(dev, k); + /* + * Software index pulse forces the preload register to load + * into the counter + */ + k->set_load_trig(dev, k, 0); + k->pulse_index(dev, k); /* set reload on counter overflow */ - k->SetLoadTrig(dev, k, 1); + k->set_load_trig(dev, k, 1); /* set interrupt on overflow */ - k->SetIntSrc(dev, k, INTSRC_OVER); + k->set_int_src(dev, k, S626_INTSRC_OVER); - SetLatchSource(dev, k, valueSrclatch); - /* k->SetEnable(dev,k,(uint16_t)(enab != 0)); */ + s626_set_latch_source(dev, k, value_latchsrc); + /* k->set_enable(dev, k, (uint16_t)(enab != 0)); */ } -/* TO COMPLETE */ +/* TO COMPLETE */ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct s626_private *devpriv = dev->private; uint8_t ppl[16]; struct comedi_cmd *cmd = &s->async->cmd; - struct enc_private *k; + const struct s626_enc_info *k; int tick; if (devpriv->ai_cmd_running) { - printk(KERN_ERR "s626_ai_cmd: Another ai_cmd is running %d\n", - dev->minor); + dev_err(dev->class_dev, + "s626_ai_cmd: Another ai_cmd is running\n"); return -EBUSY; } /* disable interrupt */ - writel(0, devpriv->mmio + P_IER); + writel(0, devpriv->mmio + S626_P_IER); /* clear interrupt request */ - writel(IRQ_RPS1 | IRQ_GPIO3, devpriv->mmio + P_ISR); + writel(S626_IRQ_RPS1 | S626_IRQ_GPIO3, devpriv->mmio + S626_P_ISR); /* clear any pending interrupt */ s626_dio_clear_irq(dev); - /* s626_enc_clear_irq(dev); */ + /* s626_enc_clear_irq(dev); */ /* reset ai_cmd_running flag */ devpriv->ai_cmd_running = 0; - /* test if cmd is valid */ + /* test if cmd is valid */ if (cmd == NULL) return -EINVAL; @@ -1373,17 +2113,20 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) case TRIG_FOLLOW: break; case TRIG_TIMER: - /* set a conter to generate adc trigger at scan_begin_arg interval */ - k = &encpriv[5]; + /* + * set a counter to generate adc trigger at scan_begin_arg + * interval + */ + k = &s626_enc_chan_info[5]; tick = s626_ns_to_timer((int *)&cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK); /* load timer value and enable interrupt */ s626_timer_load(dev, k, tick); - k->SetEnable(dev, k, CLKENAB_ALWAYS); + k->set_enable(dev, k, S626_CLKENAB_ALWAYS); 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); break; @@ -1393,52 +2136,53 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) case TRIG_NOW: break; case TRIG_TIMER: - /* set a conter to generate adc trigger at convert_arg interval */ - k = &encpriv[4]; + /* + * set a counter to generate adc trigger at convert_arg + * interval + */ + k = &s626_enc_chan_info[4]; tick = s626_ns_to_timer((int *)&cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); /* load timer value and enable interrupt */ s626_timer_load(dev, k, tick); - k->SetEnable(dev, k, CLKENAB_INDEX); + k->set_enable(dev, k, S626_CLKENAB_INDEX); break; case TRIG_EXT: - /* set the digital line and interrupt for convert trigger */ - if (cmd->scan_begin_src != TRIG_EXT - && cmd->start_src == TRIG_EXT) + /* 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); break; } 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; + devpriv->ai_continuous = 0; break; case TRIG_NONE: - /* continous acquisition */ - devpriv->ai_continous = 1; + /* continuous acquisition */ + devpriv->ai_continuous = 1; devpriv->ai_sample_count = 1; break; } - ResetADC(dev, ppl); + s626_reset_adc(dev, ppl); switch (cmd->start_src) { case TRIG_NOW: /* Trigger ADC scan loop start */ - /* s626_mc_enable(dev, MC2_ADC_RPS, P_MC2); */ + /* s626_mc_enable(dev, S626_MC2_ADC_RPS, S626_P_MC2); */ /* Start executing the RPS program */ - s626_mc_enable(dev, MC1_ERPS1, P_MC1); - + s626_mc_enable(dev, S626_MC1_ERPS1, S626_P_MC1); s->async->inttrig = NULL; break; case TRIG_EXT: /* configure DIO channel for acquisition trigger */ s626_dio_set_irq(dev, cmd->start_arg); - s->async->inttrig = NULL; break; case TRIG_INT: @@ -1447,7 +2191,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } /* enable interrupt */ - writel(IRQ_GPIO3 | IRQ_RPS1, devpriv->mmio + P_IER); + writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1, devpriv->mmio + S626_P_IER); return 0; } @@ -1461,11 +2205,11 @@ static int s626_ai_cmdtest(struct comedi_device *dev, /* Step 1 : check if triggers are trivially valid */ err |= cfc_check_trigger_src(&cmd->start_src, - TRIG_NOW | TRIG_INT | TRIG_EXT); + TRIG_NOW | TRIG_INT | TRIG_EXT); err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW); + TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW); err |= cfc_check_trigger_src(&cmd->convert_src, - TRIG_TIMER | TRIG_EXT | TRIG_NOW); + TRIG_TIMER | TRIG_EXT | TRIG_NOW); err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); @@ -1490,34 +2234,34 @@ static int s626_ai_cmdtest(struct comedi_device *dev, err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); if (cmd->start_src == TRIG_EXT) err |= cfc_check_trigger_arg_max(&cmd->start_arg, 39); - if (cmd->scan_begin_src == TRIG_EXT) err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 39); - if (cmd->convert_src == TRIG_EXT) err |= cfc_check_trigger_arg_max(&cmd->convert_arg, 39); -#define MAX_SPEED 200000 /* in nanoseconds */ -#define MIN_SPEED 2000000000 /* in nanoseconds */ +#define S626_MAX_SPEED 200000 /* in nanoseconds */ +#define S626_MIN_SPEED 2000000000 /* in nanoseconds */ if (cmd->scan_begin_src == TRIG_TIMER) { err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, - MAX_SPEED); + S626_MAX_SPEED); err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, - MIN_SPEED); + S626_MIN_SPEED); } else { /* external trigger */ /* should be level/edge, hi/lo specification here */ /* should specify multiple external triggers */ -/* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */ + /* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */ } if (cmd->convert_src == TRIG_TIMER) { - err |= cfc_check_trigger_arg_min(&cmd->convert_arg, MAX_SPEED); - err |= cfc_check_trigger_arg_max(&cmd->convert_arg, MIN_SPEED); + err |= cfc_check_trigger_arg_min(&cmd->convert_arg, + S626_MAX_SPEED); + err |= cfc_check_trigger_arg_max(&cmd->convert_arg, + S626_MIN_SPEED); } else { /* external trigger */ /* see above */ -/* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */ + /* err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg, 9); */ } err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); @@ -1546,10 +2290,10 @@ static int s626_ai_cmdtest(struct comedi_device *dev, 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; + cmd->scan_begin_arg < cmd->convert_arg * + cmd->scan_end_arg) { + cmd->scan_begin_arg = cmd->convert_arg * + cmd->scan_end_arg; err++; } } @@ -1565,10 +2309,10 @@ static int s626_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) struct s626_private *devpriv = dev->private; /* Stop RPS program in case it is currently running */ - s626_mc_disable(dev, MC1_ERPS1, P_MC1); + s626_mc_disable(dev, S626_MC1_ERPS1, S626_P_MC1); /* disable master interrupt */ - writel(0, devpriv->mmio + P_IER); + writel(0, devpriv->mmio + S626_P_IER); devpriv->ai_cmd_running = 0; @@ -1588,7 +2332,7 @@ static int s626_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, devpriv->ao_readback[CR_CHAN(insn->chanspec)] = data[i]; dacdata -= (0x1fff); - SetDAC(dev, chan, dacdata); + s626_set_dac(dev, chan, dacdata); } return i; @@ -1606,7 +2350,9 @@ static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, return i; } -/* *************** DIGITAL I/O FUNCTIONS *************** +/* *************** 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. @@ -1616,19 +2362,19 @@ static void s626_dio_init(struct comedi_device *dev) { uint16_t group; - /* Prepare to treat writes to WRCapSel as capture disables. */ - DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP); + /* Prepare to treat writes to WRCapSel as capture disables. */ + s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_NOEDCAP); - /* For each group of sixteen channels ... */ + /* For each group of sixteen channels ... */ for (group = 0; group < S626_DIO_BANKS; group++) { /* Disable all interrupts */ - DEBIwrite(dev, LP_WRINTSEL(group), 0); + s626_debi_write(dev, S626_LP_WRINTSEL(group), 0); /* Disable all event captures */ - DEBIwrite(dev, LP_WRCAPSEL(group), 0xffff); + s626_debi_write(dev, S626_LP_WRCAPSEL(group), 0xffff); /* Init all DIOs to default edge polarity */ - DEBIwrite(dev, LP_WREDGSEL(group), 0); + s626_debi_write(dev, S626_LP_WREDGSEL(group), 0); /* Program all outputs to inactive state */ - DEBIwrite(dev, LP_WRDOUT(group), 0); + s626_debi_write(dev, S626_LP_WRDOUT(group), 0); } } @@ -1640,9 +2386,9 @@ static int s626_dio_insn_bits(struct comedi_device *dev, unsigned long group = (unsigned long)s->private; if (comedi_dio_update_state(s, data)) - DEBIwrite(dev, LP_WRDOUT(group), s->state); + s626_debi_write(dev, S626_LP_WRDOUT(group), s->state); - data[1] = DEBIread(dev, LP_RDDIN(group)); + data[1] = s626_debi_read(dev, S626_LP_RDDIN(group)); return insn->n; } @@ -1659,42 +2405,50 @@ static int s626_dio_insn_config(struct comedi_device *dev, if (ret) return ret; - DEBIwrite(dev, LP_WRDOUT(group), s->io_bits); + s626_debi_write(dev, S626_LP_WRDOUT(group), s->io_bits); return insn->n; } -/* Now this function initializes the value of the counter (data[0]) - and set the subdevice. To complete with trigger and interrupt - configuration */ -/* FIXME: data[0] is supposed to be an INSN_CONFIG_xxx constant indicating +/* + * Now this function initializes the value of the counter (data[0]) + * and set the subdevice. To complete with trigger and interrupt + * configuration. + * + * FIXME: data[0] is supposed to be an INSN_CONFIG_xxx constant indicating * what is being configured, but this function appears to be using data[0] - * as a variable. */ + * as a variable. + */ 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. */ - (CLKENAB_INDEX << BF_CLKENAB); - /* uint16_t DisableIntSrc=TRUE; */ - /* uint32_t Preloadvalue; //Counter initial value */ - uint16_t valueSrclatch = LATCHSRC_AB_READ; - uint16_t enab = CLKENAB_ALWAYS; - struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; - - /* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */ - - k->SetMode(dev, k, Setup, TRUE); - Preload(dev, k, data[0]); - k->PulseIndex(dev, k); - SetLatchSource(dev, k, valueSrclatch); - k->SetEnable(dev, k, (uint16_t) (enab != 0)); + uint16_t setup = + /* Preload upon index. */ + (S626_LOADSRC_INDX << S626_BF_LOADSRC) | + /* Disable hardware index. */ + (S626_INDXSRC_SOFT << S626_BF_INDXSRC) | + /* Operating mode is Counter. */ + (S626_CLKSRC_COUNTER << S626_BF_CLKSRC) | + /* Active high clock. */ + (S626_CLKPOL_POS << S626_BF_CLKPOL) | + /* Clock multiplier is 1x. */ + (S626_CLKMULT_1X << S626_BF_CLKMULT) | + (S626_CLKENAB_INDEX << S626_BF_CLKENAB); + /* uint16_t disable_int_src = true; */ + /* uint32_t Preloadvalue; //Counter initial value */ + uint16_t value_latchsrc = S626_LATCHSRC_AB_READ; + uint16_t enab = S626_CLKENAB_ALWAYS; + const struct s626_enc_info *k = + &s626_enc_chan_info[CR_CHAN(insn->chanspec)]; + + /* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */ + + k->set_mode(dev, k, setup, true); + s626_preload(dev, k, data[0]); + k->pulse_index(dev, k); + s626_set_latch_source(dev, k, value_latchsrc); + k->set_enable(dev, k, (enab != 0)); return insn->n; } @@ -1703,12 +2457,12 @@ static int s626_enc_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - int n; - struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; + const struct s626_enc_info *k = + &s626_enc_chan_info[CR_CHAN(insn->chanspec)]; for (n = 0; n < insn->n; n++) - data[n] = ReadLatch(dev, k); + data[n] = s626_read_latch(dev, k); return n; } @@ -1717,31 +2471,32 @@ static int s626_enc_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { + const struct s626_enc_info *k = + &s626_enc_chan_info[CR_CHAN(insn->chanspec)]; - struct enc_private *k = &encpriv[CR_CHAN(insn->chanspec)]; - - /* Set the preload register */ - Preload(dev, k, data[0]); + /* Set the preload register */ + s626_preload(dev, k, data[0]); - /* 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); + /* + * Software index pulse forces the preload register to load + * into the counter + */ + k->set_load_trig(dev, k, 0); + k->pulse_index(dev, k); + k->set_load_trig(dev, k, 2); return 1; } -static void WriteMISC2(struct comedi_device *dev, uint16_t NewImage) +static void s626_write_misc2(struct comedi_device *dev, uint16_t new_image) { - 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. */ + s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_WENABLE); + s626_debi_write(dev, S626_LP_WRMISC2, new_image); + s626_debi_write(dev, S626_LP_MISC1, S626_MISC1_WDISABLE); } -static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma, - size_t bsize) +static void s626_close_dma_b(struct comedi_device *dev, + struct s626_buffer_dma *pdma, size_t bsize) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); void *vbptr; @@ -1749,554 +2504,46 @@ static void CloseDMAB(struct comedi_device *dev, struct bufferDMA *pdma, if (pdma == NULL) return; - /* find the matching allocation from the board struct */ - vbptr = pdma->LogicalBase; - vpptr = pdma->PhysicalBase; + /* find the matching allocation from the board struct */ + vbptr = pdma->logical_base; + vpptr = pdma->physical_base; if (vbptr) { pci_free_consistent(pcidev, bsize, vbptr, vpptr); - pdma->LogicalBase = NULL; - pdma->PhysicalBase = 0; - } -} - -/* ****** PRIVATE COUNTER FUNCTIONS ****** */ - -/* Reset a counter's index and overflow event capture flags. */ - -static void ResetCapFlags_A(struct comedi_device *dev, struct enc_private *k) -{ - DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL, - CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A); -} - -static void ResetCapFlags_B(struct comedi_device *dev, struct enc_private *k) -{ - DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL, - CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B); -} - -/* Return counter setup in a format (COUNTER_SETUP) that is consistent */ -/* for both A and B counters. */ - -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. */ - 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. */ - - /* 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. */ - (MULT_X1 << STDBIT_CLKMULT) : - ((cra >> (CRABIT_CLKMULT_A - - STDBIT_CLKMULT)) & STDMSK_CLKMULT))); - - /* Return adjusted counter setup. */ - return setup; -} - -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. */ - 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>. */ - - /* 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 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 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. - */ - -static void SetMode_A(struct comedi_device *dev, struct enc_private *k, - uint16_t Setup, uint16_t DisableIntSrc) -{ - struct s626_private *devpriv = dev->private; - register uint16_t cra; - register uint16_t crb; - 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. */ - - 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. */ - if (!DisableIntSrc) - cra |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC - - CRABIT_INTSRC_A)); - - /* 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_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. */ - (MULT_X1 << CRABIT_CLKMULT_A) : - ((setup & STDMSK_CLKMULT) << (CRABIT_CLKMULT_A - - STDBIT_CLKMULT)))); + pdma->logical_base = NULL; + pdma->physical_base = 0; } - - /* 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 (DisableIntSrc) - devpriv->CounterIntEnabs &= ~k->MyEventBits[3]; - - /* 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, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A), crb); } -static void SetMode_B(struct comedi_device *dev, struct enc_private *k, - uint16_t Setup, uint16_t DisableIntSrc) -{ - struct s626_private *devpriv = dev->private; - register uint16_t cra; - register uint16_t crb; - 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. */ - - 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. */ - if (!DisableIntSrc) - crb |= ((setup & STDMSK_INTSRC) >> (STDBIT_INTSRC - - CRBBIT_INTSRC_B)); - - /* 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. */ - 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. */ - 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. */ - (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. */ - 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 (DisableIntSrc) - devpriv->CounterIntEnabs &= ~k->MyEventBits[3]; - - /* While retaining CounterA and LatchSrc configurations, program the */ - /* new counter operating mode. */ - DEBIreplace(dev, k->MyCRA, ~(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. */ - -static void SetEnable_A(struct comedi_device *dev, struct enc_private *k, - uint16_t enab) -{ - DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_A), - enab << CRBBIT_CLKENAB_A); -} - -static void SetEnable_B(struct comedi_device *dev, struct enc_private *k, - uint16_t enab) -{ - DEBIreplace(dev, k->MyCRB, ~(CRBMSK_INTCTRL | CRBMSK_CLKENAB_B), - enab << CRBBIT_CLKENAB_B); -} - -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(struct comedi_device *dev, struct enc_private *k) -{ - return (DEBIread(dev, k->MyCRB) >> CRBBIT_CLKENAB_B) & 1; -} - -/* - * 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. - */ - -static void SetLoadTrig_A(struct comedi_device *dev, struct enc_private *k, - uint16_t Trig) -{ - DEBIreplace(dev, k->MyCRA, ~CRAMSK_LOADSRC_A, - Trig << CRABIT_LOADSRC_A); -} - -static void SetLoadTrig_B(struct comedi_device *dev, struct enc_private *k, - uint16_t Trig) -{ - DEBIreplace(dev, k->MyCRB, ~(CRBMSK_LOADSRC_B | CRBMSK_INTCTRL), - Trig << CRBBIT_LOADSRC_B); -} - -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(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. - */ - -static void SetIntSrc_A(struct comedi_device *dev, struct enc_private *k, - uint16_t IntSource) -{ - struct s626_private *devpriv = dev->private; - - /* Reset any pending counter overflow or index captures. */ - DEBIreplace(dev, k->MyCRB, ~CRBMSK_INTCTRL, - CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A); - - /* Program counter interrupt source. */ - DEBIreplace(dev, k->MyCRA, ~CRAMSK_INTSRC_A, - IntSource << CRABIT_INTSRC_A); - - /* Update MISC2 interrupt enable mask. */ - devpriv->CounterIntEnabs = - (devpriv->CounterIntEnabs & ~k-> - MyEventBits[3]) | k->MyEventBits[IntSource]; -} - -static void SetIntSrc_B(struct comedi_device *dev, struct enc_private *k, - uint16_t IntSource) -{ - struct s626_private *devpriv = dev->private; - uint16_t crb; - - /* Cache writeable CRB register image. */ - crb = DEBIread(dev, k->MyCRB) & ~CRBMSK_INTCTRL; - - /* Reset any pending counter overflow or index captures. */ - DEBIwrite(dev, k->MyCRB, - (uint16_t) (crb | CRBMSK_INTRESETCMD | CRBMSK_INTRESET_B)); - - /* Program counter interrupt source. */ - DEBIwrite(dev, k->MyCRB, - (uint16_t) ((crb & ~CRBMSK_INTSRC_B) | (IntSource << - CRBBIT_INTSRC_B))); - - /* Update MISC2 interrupt enable mask. */ - devpriv->CounterIntEnabs = - (devpriv->CounterIntEnabs & ~k-> - MyEventBits[3]) | k->MyEventBits[IntSource]; -} - -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(struct comedi_device *dev, struct enc_private *k) -{ - return (DEBIread(dev, k->MyCRB) >> CRBBIT_INTSRC_B) & 3; -} - -/* Return/set the clock multiplier. */ - -/* 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(struct comedi_device *dev, struct enc_private *k ) */ -/* { */ -/* return ( k->GetMode(dev, k ) >> STDBIT_CLKMULT ) & 3; */ -/* } */ - -/* Return/set the clock polarity. */ - -/* 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(struct comedi_device *dev, struct enc_private *k ) */ -/* { */ -/* return ( k->GetMode(dev, k ) >> STDBIT_CLKPOL ) & 1; */ -/* } */ - -/* Return/set the clock source. */ - -/* 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( struct comedi_device *dev,struct enc_private *k ) */ -/* { */ -/* return ( k->GetMode(dev, k ) >> STDBIT_CLKSRC ) & 3; */ -/* } */ - -/* Return/set the index polarity. */ - -/* 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(struct comedi_device *dev, struct enc_private *k ) */ -/* { */ -/* return ( k->GetMode(dev, k ) >> STDBIT_INDXPOL ) & 1; */ -/* } */ - -/* Return/set the index source. */ - -/* static void SetIndexSrc(struct comedi_device *dev, struct enc_private *k, uint16_t value ) */ -/* { */ -/* k->SetMode(dev, k, (uint16_t)( ( k->GetMode(dev, k ) & ~STDMSK_INDXSRC ) | ( (value != 0) << STDBIT_INDXSRC ) ), FALSE ); */ -/* } */ - -/* static uint16_t GetIndexSrc(struct comedi_device *dev, struct enc_private *k ) */ -/* { */ -/* return ( k->GetMode(dev, k ) >> STDBIT_INDXSRC ) & 1; */ -/* } */ - -/* Generate an index pulse. */ - -static void PulseIndex_A(struct comedi_device *dev, struct enc_private *k) -{ - register uint16_t cra; - - cra = DEBIread(dev, k->MyCRA); /* Pulse index. */ - DEBIwrite(dev, k->MyCRA, (uint16_t) (cra ^ CRAMSK_INDXPOL_A)); - DEBIwrite(dev, k->MyCRA, cra); -} - -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. */ - DEBIwrite(dev, k->MyCRB, (uint16_t) (crb ^ CRBMSK_INDXPOL_B)); - DEBIwrite(dev, k->MyCRB, crb); -} - -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), - }, { - .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), - }, { - .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), - }, { - .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), - }, { - .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), - }, { - .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), - }, -}; - -static void CountersInit(struct comedi_device *dev) +static void s626_counters_init(struct comedi_device *dev) { int chan; - 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. */ + const struct s626_enc_info *k; + uint16_t setup = + /* Preload upon index. */ + (S626_LOADSRC_INDX << S626_BF_LOADSRC) | + /* Disable hardware index. */ + (S626_INDXSRC_SOFT << S626_BF_INDXSRC) | + /* Operating mode is counter. */ + (S626_CLKSRC_COUNTER << S626_BF_CLKSRC) | + /* Active high clock. */ + (S626_CLKPOL_POS << S626_BF_CLKPOL) | + /* Count direction is up. */ + (S626_CNTDIR_UP << S626_BF_CLKPOL) | + /* Clock multiplier is 1x. */ + (S626_CLKMULT_1X << S626_BF_CLKMULT) | + /* Enabled by index */ + (S626_CLKENAB_INDEX << S626_BF_CLKENAB); + + /* + * 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); - k->SetIntSrc(dev, k, 0); - k->ResetCapFlags(dev, k); - k->SetEnable(dev, k, CLKENAB_ALWAYS); + k = &s626_enc_chan_info[chan]; + k->set_mode(dev, k, setup, true); + k->set_int_src(dev, k, 0); + k->reset_cap_flags(dev, k); + k->set_enable(dev, k, S626_CLKENAB_ALWAYS); } } @@ -2307,17 +2554,17 @@ static int s626_allocate_dma_buffers(struct comedi_device *dev) void *addr; dma_addr_t appdma; - addr = pci_alloc_consistent(pcidev, DMABUF_SIZE, &appdma); + addr = pci_alloc_consistent(pcidev, S626_DMABUF_SIZE, &appdma); if (!addr) return -ENOMEM; - devpriv->ANABuf.LogicalBase = addr; - devpriv->ANABuf.PhysicalBase = appdma; + devpriv->ana_buf.logical_base = addr; + devpriv->ana_buf.physical_base = appdma; - addr = pci_alloc_consistent(pcidev, DMABUF_SIZE, &appdma); + addr = pci_alloc_consistent(pcidev, S626_DMABUF_SIZE, &appdma); if (!addr) return -ENOMEM; - devpriv->RPSBuf.LogicalBase = addr; - devpriv->RPSBuf.PhysicalBase = appdma; + devpriv->rps_buf.logical_base = addr; + devpriv->rps_buf.physical_base = appdma; return 0; } @@ -2325,42 +2572,43 @@ static int s626_allocate_dma_buffers(struct comedi_device *dev) static void s626_initialize(struct comedi_device *dev) { struct s626_private *devpriv = dev->private; - dma_addr_t pPhysBuf; + dma_addr_t phys_buf; uint16_t chan; int i; /* Enable DEBI and audio pins, enable I2C interface */ - s626_mc_enable(dev, MC1_DEBI | MC1_AUDIO | MC1_I2C, P_MC1); + s626_mc_enable(dev, S626_MC1_DEBI | S626_MC1_AUDIO | S626_MC1_I2C, + S626_P_MC1); /* - * Configure DEBI operating mode + * Configure DEBI operating mode * - * Local bus is 16 bits wide - * Declare DEBI transfer timeout interval - * Set up byte lane steering - * Intel-compatible local bus (DEBI never times out) + * Local bus is 16 bits wide + * Declare DEBI transfer timeout interval + * Set up byte lane steering + * Intel-compatible local bus (DEBI never times out) */ - writel(DEBI_CFG_SLAVE16 | - (DEBI_TOUT << DEBI_CFG_TOUT_BIT) | - DEBI_SWAP | DEBI_CFG_INTEL, - devpriv->mmio + P_DEBICFG); + writel(S626_DEBI_CFG_SLAVE16 | + (S626_DEBI_TOUT << S626_DEBI_CFG_TOUT_BIT) | S626_DEBI_SWAP | + S626_DEBI_CFG_INTEL, devpriv->mmio + S626_P_DEBICFG); /* Disable MMU paging */ - writel(DEBI_PAGE_DISABLE, devpriv->mmio + P_DEBIPAGE); + writel(S626_DEBI_PAGE_DISABLE, devpriv->mmio + S626_P_DEBIPAGE); /* Init GPIO so that ADC Start* is negated */ - writel(GPIO_BASE | GPIO1_HI, devpriv->mmio + P_GPIO); + writel(S626_GPIO_BASE | S626_GPIO1_HI, devpriv->mmio + S626_P_GPIO); /* I2C device address for onboard eeprom (revb) */ - devpriv->I2CAdrs = 0xA0; + devpriv->i2c_adrs = 0xA0; /* * Issue an I2C ABORT command to halt any I2C * operation in progress and reset BUSY flag. */ - writel(I2C_CLKSEL | I2C_ABORT, devpriv->mmio + P_I2CSTAT); - s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2); - while (!(readl(devpriv->mmio + P_MC2) & MC2_UPLD_IIC)) + writel(S626_I2C_CLKSEL | S626_I2C_ABORT, + devpriv->mmio + S626_P_I2CSTAT); + s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); + while (!(readl(devpriv->mmio + S626_P_MC2) & S626_MC2_UPLD_IIC)) ; /* @@ -2368,9 +2616,9 @@ static void s626_initialize(struct comedi_device *dev) * reg twice to reset all I2C error flags. */ for (i = 0; i < 2; i++) { - writel(I2C_CLKSEL, devpriv->mmio + P_I2CSTAT); - s626_mc_enable(dev, MC2_UPLD_IIC, P_MC2); - while (!s626_mc_test(dev, MC2_UPLD_IIC, P_MC2)) + writel(S626_I2C_CLKSEL, devpriv->mmio + S626_P_I2CSTAT); + s626_mc_enable(dev, S626_MC2_UPLD_IIC, S626_P_MC2); + while (!s626_mc_test(dev, S626_MC2_UPLD_IIC, S626_P_MC2)) ; } @@ -2380,31 +2628,32 @@ static void s626_initialize(struct comedi_device *dev) * DAC data setup times are satisfied, enable DAC serial * clock out. */ - writel(ACON2_INIT, devpriv->mmio + P_ACON2); + writel(S626_ACON2_INIT, devpriv->mmio + S626_P_ACON2); /* * 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 + * accumulation of ADC data: S626_RSD1 = shift data in on SD1. + * S626_SIB_A1 = store data uint8_t at next available location * in FB BUFFER1 register. */ - writel(RSD1 | SIB_A1, devpriv->mmio + P_TSL1); - writel(RSD1 | SIB_A1 | EOS, devpriv->mmio + P_TSL1 + 4); + writel(S626_RSD1 | S626_SIB_A1, devpriv->mmio + S626_P_TSL1); + writel(S626_RSD1 | S626_SIB_A1 | S626_EOS, + devpriv->mmio + S626_P_TSL1 + 4); /* Enable TSL1 slot list so that it executes all the time */ - writel(ACON1_ADCSTART, devpriv->mmio + P_ACON1); + writel(S626_ACON1_ADCSTART, devpriv->mmio + S626_P_ACON1); /* * Initialize RPS registers used for ADC */ /* Physical start of RPS program */ - writel((uint32_t)devpriv->RPSBuf.PhysicalBase, - devpriv->mmio + P_RPSADDR1); + writel((uint32_t)devpriv->rps_buf.physical_base, + devpriv->mmio + S626_P_RPSADDR1); /* RPS program performs no explicit mem writes */ - writel(0, devpriv->mmio + P_RPSPAGE1); + writel(0, devpriv->mmio + S626_P_RPSPAGE1); /* Disable RPS timeouts */ - writel(0, devpriv->mmio + P_RPS1_TOUT); + writel(0, devpriv->mmio + S626_P_RPS1_TOUT); #if 0 /* @@ -2416,38 +2665,37 @@ static void s626_initialize(struct comedi_device *dev) * because the SAA7146 ADC interface does not start up in * a defined state after a PCI reset. */ - { - uint8_t PollList; - uint16_t AdcData; - uint16_t StartVal; - uint16_t index; - unsigned int data[16]; + uint8_t poll_list; + uint16_t adc_data; + uint16_t start_val; + uint16_t index; + unsigned int data[16]; - /* Create a simple polling list for analog input channel 0 */ - PollList = EOPL; - ResetADC(dev, &PollList); + /* Create a simple polling list for analog input channel 0 */ + poll_list = S626_EOPL; + s626_reset_adc(dev, &poll_list); - /* Get initial ADC value */ - s626_ai_rinsn(dev, dev->subdevices, NULL, data); - StartVal = data[0]; - - /* - * VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED EXECUTION. - * - * Invoke ADCs until the new ADC value differs from the initial - * value or a timeout occurs. The timeout protects against the - * possibility that the driver is restarting and the ADC data is a - * fixed value resulting from the applied ADC analog input being - * unusually quiet or at the rail. - */ - for (index = 0; index < 500; index++) { + /* Get initial ADC value */ s626_ai_rinsn(dev, dev->subdevices, NULL, data); - AdcData = data[0]; - if (AdcData != StartVal) - break; - } + start_val = data[0]; + /* + * VERSION 2.01 CHANGE: TIMEOUT ADDED TO PREVENT HANGED + * EXECUTION. + * + * Invoke ADCs until the new ADC value differs from the initial + * value or a timeout occurs. The timeout protects against the + * possibility that the driver is restarting and the ADC data is + * a fixed value resulting from the applied ADC analog input + * being unusually quiet or at the rail. + */ + for (index = 0; index < 500; index++) { + s626_ai_rinsn(dev, dev->subdevices, NULL, data); + adc_data = data[0]; + if (adc_data != start_val) + break; + } } #endif /* SAA7146 BUG WORKAROUND */ @@ -2460,7 +2708,7 @@ static void s626_initialize(struct comedi_device *dev) * burst length = 1 DWORD * threshold = 1 DWORD. */ - writel(0, devpriv->mmio + P_PCI_BT_A); + writel(0, devpriv->mmio + S626_P_PCI_BT_A); /* * Init Audio2's output DMA physical addresses. The protection @@ -2468,18 +2716,18 @@ static void s626_initialize(struct comedi_device *dev) * single DWORD will be transferred each time a DMA transfer is * enabled. */ - pPhysBuf = devpriv->ANABuf.PhysicalBase + - (DAC_WDMABUF_OS * sizeof(uint32_t)); - writel((uint32_t)pPhysBuf, devpriv->mmio + P_BASEA2_OUT); - writel((uint32_t)(pPhysBuf + sizeof(uint32_t)), - devpriv->mmio + P_PROTA2_OUT); + phys_buf = devpriv->ana_buf.physical_base + + (S626_DAC_WDMABUF_OS * sizeof(uint32_t)); + writel((uint32_t)phys_buf, devpriv->mmio + S626_P_BASEA2_OUT); + writel((uint32_t)(phys_buf + sizeof(uint32_t)), + devpriv->mmio + S626_P_PROTA2_OUT); /* * 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; + devpriv->dac_wbuf = (uint32_t *)devpriv->ana_buf.logical_base + + S626_DAC_WDMABUF_OS; /* * Audio2's output channels does not use paging. The @@ -2487,7 +2735,7 @@ static void s626_initialize(struct comedi_device *dev) * DMAC will automatically halt and its PCI address pointer * will be reset when the protection address is reached. */ - writel(8, devpriv->mmio + P_PAGEA2_OUT); + writel(8, devpriv->mmio + S626_P_PAGEA2_OUT); /* * Initialize time slot list 2 (TSL2), which is used to control @@ -2502,7 +2750,8 @@ static void s626_initialize(struct comedi_device *dev) */ /* Slot 0: Trap TSL execution, shift 0xFF into FB_BUFFER2 */ - writel(XSD2 | RSD3 | SIB_A2 | EOS, devpriv->mmio + VECTPORT(0)); + writel(S626_XSD2 | S626_RSD3 | S626_SIB_A2 | S626_EOS, + devpriv->mmio + S626_VECTPORT(0)); /* * Initialize slot 1, which is constant. Slot 1 causes a @@ -2514,18 +2763,18 @@ static void s626_initialize(struct comedi_device *dev) */ /* Slot 1: Fetch DWORD from Audio2's output FIFO */ - writel(LF_A2, devpriv->mmio + VECTPORT(1)); + writel(S626_LF_A2, devpriv->mmio + S626_VECTPORT(1)); /* Start DAC's audio interface (TSL2) running */ - writel(ACON1_DACSTART, devpriv->mmio + P_ACON1); + writel(S626_ACON1_DACSTART, devpriv->mmio + S626_P_ACON1); /* * 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); + s626_load_trim_dacs(dev); + s626_load_trim_dacs(dev); /* * Manually init all gate array hardware in case this is a soft @@ -2540,10 +2789,10 @@ static void s626_initialize(struct comedi_device *dev) * polarity images. */ for (chan = 0; chan < S626_DAC_CHANNELS; chan++) - SetDAC(dev, chan, 0); + s626_set_dac(dev, chan, 0); /* Init counters */ - CountersInit(dev); + s626_counters_init(dev); /* * Without modifying the state of the Battery Backup enab, disable @@ -2551,8 +2800,8 @@ static void s626_initialize(struct comedi_device *dev) * 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)); + s626_write_misc2(dev, (s626_debi_read(dev, S626_LP_RDMISC2) & + S626_MISC2_BATT_ENABLE)); /* Initialize the digital I/O subsystem */ s626_dio_init(dev); @@ -2579,10 +2828,10 @@ static int s626_auto_attach(struct comedi_device *dev, return -ENOMEM; /* disable master interrupt */ - writel(0, devpriv->mmio + P_IER); + writel(0, devpriv->mmio + S626_P_IER); /* soft reset */ - writel(MC1_SOFT_RESET, devpriv->mmio + P_MC1); + writel(S626_MC1_SOFT_RESET, devpriv->mmio + S626_P_MC1); /* DMA FIXME DMA// */ @@ -2661,7 +2910,7 @@ static int s626_auto_attach(struct comedi_device *dev, s->io_bits = 0xffff; s->private = (void *)2; /* DIO group 2 */ s->range_table = &range_digital; - s->insn_config = s626_dio_insn_config; + s->insn_config = s626_dio_insn_config; s->insn_bits = s626_dio_insn_bits; s = &dev->subdevices[5]; @@ -2670,7 +2919,6 @@ static int s626_auto_attach(struct comedi_device *dev, s->subdev_flags = SDF_WRITABLE | SDF_READABLE | SDF_LSAMPL; s->n_chan = S626_ENCODER_CHANNELS; s->maxdata = 0xffffff; - s->private = enc_private_data; s->range_table = &range_unknown; s->insn_config = s626_enc_insn_config; s->insn_read = s626_enc_insn_read; @@ -2694,20 +2942,22 @@ static void s626_detach(struct comedi_device *dev) if (devpriv->mmio) { /* interrupt mask */ /* Disable master interrupt */ - writel(0, devpriv->mmio + P_IER); + writel(0, devpriv->mmio + S626_P_IER); /* Clear board's IRQ status flag */ - writel(IRQ_GPIO3 | IRQ_RPS1, - devpriv->mmio + P_ISR); + writel(S626_IRQ_GPIO3 | S626_IRQ_RPS1, + devpriv->mmio + S626_P_ISR); - /* Disable the watchdog timer and battery charger. */ - WriteMISC2(dev, 0); + /* Disable the watchdog timer and battery charger. */ + s626_write_misc2(dev, 0); /* Close all interfaces on 7146 device */ - writel(MC1_SHUTDOWN, devpriv->mmio + P_MC1); - writel(ACON1_BASE, devpriv->mmio + P_ACON1); + writel(S626_MC1_SHUTDOWN, devpriv->mmio + S626_P_MC1); + writel(S626_ACON1_BASE, devpriv->mmio + S626_P_ACON1); - CloseDMAB(dev, &devpriv->RPSBuf, DMABUF_SIZE); - CloseDMAB(dev, &devpriv->ANABuf, DMABUF_SIZE); + s626_close_dma_b(dev, &devpriv->rps_buf, + S626_DMABUF_SIZE); + s626_close_dma_b(dev, &devpriv->ana_buf, + S626_DMABUF_SIZE); } if (dev->irq) @@ -2737,8 +2987,8 @@ static int s626_pci_probe(struct pci_dev *dev, * Philips SAA7146 media/dvb based cards. */ static DEFINE_PCI_DEVICE_TABLE(s626_pci_table) = { - { PCI_VENDOR_ID_S626, PCI_DEVICE_ID_S626, - PCI_SUBVENDOR_ID_S626, PCI_SUBDEVICE_ID_S626, 0, 0, 0 }, + { PCI_DEVICE_SUB(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, + 0x6000, 0x0272) }, { 0 } }; MODULE_DEVICE_TABLE(pci, s626_pci_table); diff --git a/drivers/staging/comedi/drivers/s626.h b/drivers/staging/comedi/drivers/s626.h index a85e6bdcad07..9b6ab0d398d6 100644 --- a/drivers/staging/comedi/drivers/s626.h +++ b/drivers/staging/comedi/drivers/s626.h @@ -1,690 +1,606 @@ /* - comedi/drivers/s626.h - Sensoray s626 Comedi driver, header file - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 2000 David A. Schleef <[email protected]> - - Based on Sensoray Model 626 Linux driver Version 0.2 - Copyright (C) 2002-2004 Sensoray Co., 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. -*/ - -/* - Driver: s626.o (s626.ko) - Description: Sensoray 626 driver - Devices: Sensoray s626 - Authors: Gianluca Palli <[email protected]>, - Updated: Thu, 12 Jul 2005 - Status: experimental - - Configuration Options: - analog input: - none - - analog output: - none - - digital channel: - s626 has 3 dio subdevices (2,3 and 4) each with 16 i/o channels - supported configuration options: - INSN_CONFIG_DIO_QUERY - COMEDI_INPUT - COMEDI_OUTPUT - - encoder: - Every channel must be configured before reading. - - 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 - - comedi_do_insn(cf,&insn); // executing configuration -*/ - -#if !defined(TRUE) -#define TRUE (1) -#endif - -#if !defined(FALSE) -#define FALSE (0) -#endif - -#define S626_SIZE 0x0200 -#define DMABUF_SIZE 4096 /* 4k pages */ + * comedi/drivers/s626.h + * Sensoray s626 Comedi driver, header file + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef <[email protected]> + * + * Based on Sensoray Model 626 Linux driver Version 0.2 + * Copyright (C) 2002-2004 Sensoray Co., 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. + */ + +#ifndef S626_H_INCLUDED +#define S626_H_INCLUDED + +#define S626_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 NUM_TRIMDACS 12 /* Number of valid TrimDAC channels. */ - -/* PCI bus interface types. */ -#define INTEL 1 /* Intel bus type. */ -#define MOTOROLA 2 /* Motorola bus type. */ +#define S626_DIO_BANKS 3 /* Number of DIO groups. */ +#define S626_DIO_EXTCHANS 40 /* Number of extended-capability + * DIO channels. */ -#define PLATFORM INTEL /* *** SELECT PLATFORM TYPE *** */ +#define S626_NUM_TRIMDACS 12 /* Number of valid TrimDAC channels. */ -#define RANGE_5V 0x10 /* +/-5V range */ -#define RANGE_10V 0x00 /* +/-10V range */ +/* PCI bus interface types. */ +#define S626_INTEL 1 /* Intel bus type. */ +#define S626_MOTOROLA 2 /* Motorola bus type. */ -#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 S626_PLATFORM S626_INTEL /* *** SELECT PLATFORM TYPE *** */ -/* 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. */ +#define S626_RANGE_5V 0x10 /* +/-5V range */ +#define S626_RANGE_10V 0x00 /* +/-10V range */ -/* 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. */ +#define S626_EOPL 0x80 /* End of ADC poll list marker. */ +#define S626_GSEL_BIPOLAR5V 0x00F0 /* S626_LP_GSEL setting 5V bipolar. */ +#define S626_GSEL_BIPOLAR10V 0x00A0 /* S626_LP_GSEL setting 10V bipolar. */ -/* All remaining space in 4KB DMA buffer is available for the RPS1 program. */ +/* Error codes that must be visible to this base class. */ +#define S626_ERR_ILLEGAL_PARM 0x00010000 /* Illegal function parameter + * value was specified. */ +#define S626_ERR_I2C 0x00020000 /* I2C error. */ +#define S626_ERR_COUNTERSETUP 0x00200000 /* Illegal setup specified for + * counter channel. */ +#define S626_ERR_DEBI_TIMEOUT 0x00400000 /* DEBI transfer timed out. */ -/* 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. */ -#define IRQ_RPS1 0x10000000 -#define ISR_AFOU 0x00000800 +/* + * Organization (physical order) and size (in DWORDs) of logical DMA buffers + * contained by ANA_DMABUF. + */ +#define S626_ADC_DMABUF_DWORDS 40 /* ADC DMA buffer must hold 16 samples, + * plus pre/post garbage samples. */ +#define S626_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. */ + +/* Address offsets, in DWORDS, from base of DMA buffer. */ +#define S626_DAC_WDMABUF_OS S626_ADC_DMABUF_DWORDS + +/* Interrupt enable bit in ISR and IER. */ +#define S626_IRQ_GPIO3 0x00000040 /* IRQ enable for GPIO3. */ +#define S626_IRQ_RPS1 0x10000000 +#define S626_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 */ - -/* 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_LOGICAL_OR 0x08000000 /* Logical OR conditionals. */ -#define RPS_INVERT 0x04000000 /* Test for negated semaphores. */ -#define RPS_DEBI 0x00000002 /* DEBI done */ - -#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_SIGADC RPS_SIG0 /* Trigger/status for ADC's RPS program. */ -#define RPS_SIGDAC RPS_SIG1 /* Trigger/status for DAC's RPS program. */ - -/* 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. */ - -/* Event counter source addresses. */ -#define SBA_RPS_A0 0x27 /* Time of RPS0 busy, in PCI clocks. */ - -/* 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. */ - -/* 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. */ - -/* Secondary Status Register (SSR) constants. */ -#define SSR_AF2_OUT 0x00000200 /* Audio 2 output FIFO under/overflow detected. */ - -/* 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. */ - -#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 - -#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_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. */ - -/* 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 +#define S626_IRQ_COINT1A 0x0400 /* counter 1A overflow interrupt mask */ +#define S626_IRQ_COINT1B 0x0800 /* counter 1B overflow interrupt mask */ +#define S626_IRQ_COINT2A 0x1000 /* counter 2A overflow interrupt mask */ +#define S626_IRQ_COINT2B 0x2000 /* counter 2B overflow interrupt mask */ +#define S626_IRQ_COINT3A 0x4000 /* counter 3A overflow interrupt mask */ +#define S626_IRQ_COINT3B 0x8000 /* counter 3B overflow interrupt mask */ + +/* RPS command codes. */ +#define S626_RPS_CLRSIGNAL 0x00000000 /* CLEAR SIGNAL */ +#define S626_RPS_SETSIGNAL 0x10000000 /* SET SIGNAL */ +#define S626_RPS_NOP 0x00000000 /* NOP */ +#define S626_RPS_PAUSE 0x20000000 /* PAUSE */ +#define S626_RPS_UPLOAD 0x40000000 /* UPLOAD */ +#define S626_RPS_JUMP 0x80000000 /* JUMP */ +#define S626_RPS_LDREG 0x90000100 /* LDREG (1 uint32_t only) */ +#define S626_RPS_STREG 0xA0000100 /* STREG (1 uint32_t only) */ +#define S626_RPS_STOP 0x50000000 /* STOP */ +#define S626_RPS_IRQ 0x60000000 /* IRQ */ + +#define S626_RPS_LOGICAL_OR 0x08000000 /* Logical OR conditionals. */ +#define S626_RPS_INVERT 0x04000000 /* Test for negated + * semaphores. */ +#define S626_RPS_DEBI 0x00000002 /* DEBI done */ + +#define S626_RPS_SIG0 0x00200000 /* RPS semaphore 0 + * (used by ADC). */ +#define S626_RPS_SIG1 0x00400000 /* RPS semaphore 1 + * (used by DAC). */ +#define S626_RPS_SIG2 0x00800000 /* RPS semaphore 2 + * (not used). */ +#define S626_RPS_GPIO2 0x00080000 /* RPS GPIO2 */ +#define S626_RPS_GPIO3 0x00100000 /* RPS GPIO3 */ + +#define S626_RPS_SIGADC S626_RPS_SIG0 /* Trigger/status for + * ADC's RPS program. */ +#define S626_RPS_SIGDAC S626_RPS_SIG1 /* Trigger/status for + * DAC's RPS program. */ + +/* RPS clock parameters. */ +#define S626_RPSCLK_SCALAR 8 /* This is apparent ratio of + * PCI/RPS clks (undocumented!!). */ +#define S626_RPSCLK_PER_US (33 / S626_RPSCLK_SCALAR) + /* Number of RPS clocks in one + * microsecond. */ + +/* Event counter source addresses. */ +#define S626_SBA_RPS_A0 0x27 /* Time of RPS0 busy, in PCI clocks. */ + +/* GPIO constants. */ +#define S626_GPIO_BASE 0x10004000 /* GPIO 0,2,3 = inputs, + * GPIO3 = IRQ; GPIO1 = out. */ +#define S626_GPIO1_LO 0x00000000 /* GPIO1 set to LOW. */ +#define S626_GPIO1_HI 0x00001000 /* GPIO1 set to HIGH. */ + +/* Primary Status Register (PSR) constants. */ +#define S626_PSR_DEBI_E 0x00040000 /* DEBI event flag. */ +#define S626_PSR_DEBI_S 0x00080000 /* DEBI status flag. */ +#define S626_PSR_A2_IN 0x00008000 /* Audio output DMA2 protection + * address reached. */ +#define S626_PSR_AFOU 0x00000800 /* Audio FIFO under/overflow + * detected. */ +#define S626_PSR_GPIO2 0x00000020 /* GPIO2 input pin: 0=AdcBusy, + * 1=AdcIdle. */ +#define S626_PSR_EC0S 0x00000001 /* Event counter 0 threshold + * reached. */ + +/* Secondary Status Register (SSR) constants. */ +#define S626_SSR_AF2_OUT 0x00000200 /* Audio 2 output FIFO + * under/overflow detected. */ + +/* Master Control Register 1 (MC1) constants. */ +#define S626_MC1_SOFT_RESET 0x80000000 /* Invoke 7146 soft reset. */ +#define S626_MC1_SHUTDOWN 0x3FFF0000 /* Shut down all MC1-controlled + * enables. */ + +#define S626_MC1_ERPS1 0x2000 /* Enab/disable RPS task 1. */ +#define S626_MC1_ERPS0 0x1000 /* Enab/disable RPS task 0. */ +#define S626_MC1_DEBI 0x0800 /* Enab/disable DEBI pins. */ +#define S626_MC1_AUDIO 0x0200 /* Enab/disable audio port pins. */ +#define S626_MC1_I2C 0x0100 /* Enab/disable I2C interface. */ +#define S626_MC1_A2OUT 0x0008 /* Enab/disable transfer on A2 out. */ +#define S626_MC1_A2IN 0x0004 /* Enab/disable transfer on A2 in. */ +#define S626_MC1_A1IN 0x0001 /* Enab/disable transfer on A1 in. */ + +/* Master Control Register 2 (MC2) constants. */ +#define S626_MC2_UPLD_DEBI 0x0002 /* Upload DEBI. */ +#define S626_MC2_UPLD_IIC 0x0001 /* Upload I2C. */ +#define S626_MC2_RPSSIG2 0x2000 /* RPS signal 2 (not used). */ +#define S626_MC2_RPSSIG1 0x1000 /* RPS signal 1 (DAC RPS busy). */ +#define S626_MC2_RPSSIG0 0x0800 /* RPS signal 0 (ADC RPS busy). */ + +#define S626_MC2_ADC_RPS S626_MC2_RPSSIG0 /* ADC RPS busy. */ +#define S626_MC2_DAC_RPS S626_MC2_RPSSIG1 /* DAC RPS busy. */ + +/* PCI BUS (SAA7146) REGISTER ADDRESS OFFSETS */ +#define S626_P_PCI_BT_A 0x004C /* Audio DMA burst/threshold control. */ +#define S626_P_DEBICFG 0x007C /* DEBI configuration. */ +#define S626_P_DEBICMD 0x0080 /* DEBI command. */ +#define S626_P_DEBIPAGE 0x0084 /* DEBI page. */ +#define S626_P_DEBIAD 0x0088 /* DEBI target address. */ +#define S626_P_I2CCTRL 0x008C /* I2C control. */ +#define S626_P_I2CSTAT 0x0090 /* I2C status. */ +#define S626_P_BASEA2_IN 0x00AC /* Audio input 2 base physical DMAbuf * address. */ -#define P_PROTA2_IN 0x00B0 /* Audio input 2 physical DMAbuf +#define S626_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 +#define S626_P_PAGEA2_IN 0x00B4 /* Audio input 2 paging attributes. */ +#define S626_P_BASEA2_OUT 0x00B8 /* Audio output 2 base physical DMAbuf * address. */ -#define P_PROTA2_OUT 0x00BC /* Audio output 2 physical DMAbuf +#define S626_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 +#define S626_P_PAGEA2_OUT 0x00C0 /* Audio output 2 paging attributes. */ +#define S626_P_RPSPAGE0 0x00C4 /* RPS0 page. */ +#define S626_P_RPSPAGE1 0x00C8 /* RPS1 page. */ +#define S626_P_RPS0_TOUT 0x00D4 /* RPS0 time-out. */ +#define S626_P_RPS1_TOUT 0x00D8 /* RPS1 time-out. */ +#define S626_P_IER 0x00DC /* Interrupt enable. */ +#define S626_P_GPIO 0x00E0 /* General-purpose I/O. */ +#define S626_P_EC1SSR 0x00E4 /* Event counter set 1 source select. */ +#define S626_P_ECT1R 0x00EC /* Event counter threshold set 1. */ +#define S626_P_ACON1 0x00F4 /* Audio control 1. */ +#define S626_P_ACON2 0x00F8 /* Audio control 2. */ +#define S626_P_MC1 0x00FC /* Master control 1. */ +#define S626_P_MC2 0x0100 /* Master control 2. */ +#define S626_P_RPSADDR0 0x0104 /* RPS0 instruction pointer. */ +#define S626_P_RPSADDR1 0x0108 /* RPS1 instruction pointer. */ +#define S626_P_ISR 0x010C /* Interrupt status. */ +#define S626_P_PSR 0x0110 /* Primary status. */ +#define S626_P_SSR 0x0114 /* Secondary status. */ +#define S626_P_EC1R 0x0118 /* Event counter set 1. */ +#define S626_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. */ +#define S626_P_FB_BUFFER1 0x0144 /* Audio feedback buffer 1. */ +#define S626_P_FB_BUFFER2 0x0148 /* Audio feedback buffer 2. */ +#define S626_P_TSL1 0x0180 /* Audio time slot list 1. */ +#define S626_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. */ +/* LOCAL BUS (GATE ARRAY) REGISTER ADDRESS OFFSETS */ +/* Analog I/O registers: */ +#define S626_LP_DACPOL 0x0082 /* Write DAC polarity. */ +#define S626_LP_GSEL 0x0084 /* Write ADC gain. */ +#define S626_LP_ISEL 0x0086 /* Write ADC channel select. */ /* Digital I/O registers */ -#define LP_RDDIN(x) (0x0040 + (x) * 0x10) /* R: digital input */ -#define LP_WRINTSEL(x) (0x0042 + (x) * 0x10) /* W: int enable */ -#define LP_WREDGSEL(x) (0x0044 + (x) * 0x10) /* W: edge selection */ -#define LP_WRCAPSEL(x) (0x0046 + (x) * 0x10) /* W: capture enable */ -#define LP_RDCAPFLG(x) (0x0048 + (x) * 0x10) /* R: edges captured */ -#define LP_WRDOUT(x) (0x0048 + (x) * 0x10) /* W: digital output */ -#define LP_RDINTSEL(x) (0x004a + (x) * 0x10) /* R: int enable */ -#define LP_RDEDGSEL(x) (0x004c + (x) * 0x10) /* R: edge selection */ -#define LP_RDCAPSEL(x) (0x004e + (x) * 0x10) /* R: capture enable */ - -/* 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. */ - -/* Bit masks for MISC1 register that are the same for reads and writes. */ -#define MISC1_WENABLE 0x8000 /* enab writes to MISC2 (except Clear +#define S626_LP_RDDIN(x) (0x0040 + (x) * 0x10) /* R: digital input */ +#define S626_LP_WRINTSEL(x) (0x0042 + (x) * 0x10) /* W: int enable */ +#define S626_LP_WREDGSEL(x) (0x0044 + (x) * 0x10) /* W: edge selection */ +#define S626_LP_WRCAPSEL(x) (0x0046 + (x) * 0x10) /* W: capture enable */ +#define S626_LP_RDCAPFLG(x) (0x0048 + (x) * 0x10) /* R: edges captured */ +#define S626_LP_WRDOUT(x) (0x0048 + (x) * 0x10) /* W: digital output */ +#define S626_LP_RDINTSEL(x) (0x004a + (x) * 0x10) /* R: int enable */ +#define S626_LP_RDEDGSEL(x) (0x004c + (x) * 0x10) /* R: edge selection */ +#define S626_LP_RDCAPSEL(x) (0x004e + (x) * 0x10) /* R: capture enable */ + +/* Counter Registers (read/write): */ +#define S626_LP_CR0A 0x0000 /* 0A setup register. */ +#define S626_LP_CR0B 0x0002 /* 0B setup register. */ +#define S626_LP_CR1A 0x0004 /* 1A setup register. */ +#define S626_LP_CR1B 0x0006 /* 1B setup register. */ +#define S626_LP_CR2A 0x0008 /* 2A setup register. */ +#define S626_LP_CR2B 0x000A /* 2B setup register. */ + +/* Counter PreLoad (write) and Latch (read) Registers: */ +#define S626_LP_CNTR0ALSW 0x000C /* 0A lsw. */ +#define S626_LP_CNTR0AMSW 0x000E /* 0A msw. */ +#define S626_LP_CNTR0BLSW 0x0010 /* 0B lsw. */ +#define S626_LP_CNTR0BMSW 0x0012 /* 0B msw. */ +#define S626_LP_CNTR1ALSW 0x0014 /* 1A lsw. */ +#define S626_LP_CNTR1AMSW 0x0016 /* 1A msw. */ +#define S626_LP_CNTR1BLSW 0x0018 /* 1B lsw. */ +#define S626_LP_CNTR1BMSW 0x001A /* 1B msw. */ +#define S626_LP_CNTR2ALSW 0x001C /* 2A lsw. */ +#define S626_LP_CNTR2AMSW 0x001E /* 2A msw. */ +#define S626_LP_CNTR2BLSW 0x0020 /* 2B lsw. */ +#define S626_LP_CNTR2BMSW 0x0022 /* 2B msw. */ + +/* Miscellaneous Registers (read/write): */ +#define S626_LP_MISC1 0x0088 /* Read/write Misc1. */ +#define S626_LP_WRMISC2 0x0090 /* Write Misc2. */ +#define S626_LP_RDMISC2 0x0082 /* Read Misc2. */ + +/* Bit masks for MISC1 register that are the same for reads and writes. */ +#define S626_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 +#define S626_MISC1_WDISABLE 0x0000 /* Disable writes to MISC2. */ +#define S626_MISC1_EDCAP 0x1000 /* Enable edge capture on DIO chans + * specified by S626_LP_WRCAPSELx. */ +#define S626_MISC1_NOEDCAP 0x0000 /* Disable edge capture on specified * DIO chans. */ -/* Bit masks for MISC1 register reads. */ -#define RDMISC1_WDTIMEOUT 0x4000 /* Watchdog timer timed out. */ - -/* 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) +/* Bit masks for MISC1 register reads. */ +#define S626_RDMISC1_WDTIMEOUT 0x4000 /* Watchdog timer timed out. */ + +/* Bit masks for MISC2 register writes. */ +#define S626_WRMISC2_WDCLEAR 0x8000 /* Reset watchdog timer to zero. */ +#define S626_WRMISC2_CHARGE_ENABLE 0x4000 /* Enable battery trickle charging. */ + +/* Bit masks for MISC2 register that are the same for reads and writes. */ +#define S626_MISC2_BATT_ENABLE 0x0008 /* Backup battery enable. */ +#define S626_MISC2_WDENABLE 0x0004 /* Watchdog timer enable. */ +#define S626_MISC2_WDPERIOD_MASK 0x0003 /* Watchdog interval select mask. */ + +/* Bit masks for ACON1 register. */ +#define S626_A2_RUN 0x40000000 /* Run A2 based on TSL2. */ +#define S626_A1_RUN 0x20000000 /* Run A1 based on TSL1. */ +#define S626_A1_SWAP 0x00200000 /* Use big-endian for A1. */ +#define S626_A2_SWAP 0x00100000 /* Use big-endian for A2. */ +#define S626_WS_MODES 0x00019999 /* WS0 = TSL1 trigger input, + * WS1-WS4 = CS* outputs. */ + +#if S626_PLATFORM == S626_INTEL /* Base ACON1 config: always run + * A1 based on TSL1. */ +#define S626_ACON1_BASE (S626_WS_MODES | S626_A1_RUN) +#elif S626_PLATFORM == S626_MOTOROLA +#define S626_ACON1_BASE \ + (S626_WS_MODES | S626_A1_RUN | S626_A1_SWAP | S626_A2_SWAP) #endif -#define ACON1_ADCSTART ACON1_BASE /* Start ADC: run A1 - * based on TSL1. */ -#define ACON1_DACSTART (ACON1_BASE | A2_RUN) +#define S626_ACON1_ADCSTART S626_ACON1_BASE /* Start ADC: run A1 + * based on TSL1. */ +#define S626_ACON1_DACSTART (S626_ACON1_BASE | S626_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. */ - -#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. */ -#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 +#define S626_ACON1_DACSTOP S626_ACON1_BASE /* Halt A2. */ + +/* Bit masks for ACON2 register. */ +#define S626_A1_CLKSRC_BCLK1 0x00000000 /* A1 bit rate = BCLK1 (ADC). */ +#define S626_A2_CLKSRC_X1 0x00800000 /* A2 bit rate = ACLK/1 + * (DACs). */ +#define S626_A2_CLKSRC_X2 0x00C00000 /* A2 bit rate = ACLK/2 + * (DACs). */ +#define S626_A2_CLKSRC_X4 0x01400000 /* A2 bit rate = ACLK/4 + * (DACs). */ +#define S626_INVERT_BCLK2 0x00100000 /* Invert BCLK2 (DACs). */ +#define S626_BCLK2_OE 0x00040000 /* Enable BCLK2 (DACs). */ +#define S626_ACON2_XORMASK 0x000C0000 /* XOR mask for ACON2 + * active-low bits. */ + +#define S626_ACON2_INIT (S626_ACON2_XORMASK ^ \ + (S626_A1_CLKSRC_BCLK1 | S626_A2_CLKSRC_X2 | \ + S626_INVERT_BCLK2 | S626_BCLK2_OE)) + +/* Bit masks for timeslot records. */ +#define S626_WS1 0x40000000 /* WS output to assert. */ +#define S626_WS2 0x20000000 +#define S626_WS3 0x10000000 +#define S626_WS4 0x08000000 +#define S626_RSD1 0x01000000 /* Shift A1 data in on SD1. */ +#define S626_SDW_A1 0x00800000 /* Store rcv'd char at next char + * slot of DWORD1 buffer. */ +#define S626_SIB_A1 0x00400000 /* Store rcv'd char at next * char slot of FB1 buffer. */ -#define SF_A1 0x00200000 /* Write unsigned long +#define S626_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 +#define S626_XFIFO_0 0x00000000 /* Data fifo byte 0. */ +#define S626_XFIFO_1 0x00000010 /* Data fifo byte 1. */ +#define S626_XFIFO_2 0x00000020 /* Data fifo byte 2. */ +#define S626_XFIFO_3 0x00000030 /* Data fifo byte 3. */ +#define S626_XFB0 0x00000040 /* FB_BUFFER byte 0. */ +#define S626_XFB1 0x00000050 /* FB_BUFFER byte 1. */ +#define S626_XFB2 0x00000060 /* FB_BUFFER byte 2. */ +#define S626_XFB3 0x00000070 /* FB_BUFFER byte 3. */ +#define S626_SIB_A2 0x00000200 /* Store next dword from A2's + * input shifter to FB2 + * buffer. */ +#define S626_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 +#define S626_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 manifest constants. */ - -/* 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. */ - -/* I2C read command | EEPROM address. */ -#define I2CR (devpriv->I2CAdrs | 1) - -/* I2C write command | EEPROM address. */ -#define I2CW (devpriv->I2CAdrs) - -/* 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)) - -/* 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. */ - -#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 */ - -/* 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. */ - -/* Read immediate 2 bytes. */ -#define DEBI_CMD_RDWORD (DEBI_CMD_READ | DEBI_CMD_SIZE16) - -/* Write immediate 2 bytes. */ -#define DEBI_CMD_WRWORD (DEBI_CMD_WRITE | DEBI_CMD_SIZE16) - -/* 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. */ - -/* 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. */ - -/* 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 S626_XSD2 0x00000008 /* Shift data out on SD2. */ +#define S626_RSD3 0x00001800 /* Shift data in on SD3. */ +#define S626_RSD2 0x00001000 /* Shift data in on SD2. */ +#define S626_LOW_A2 0x00000002 /* Drive last SD low for 7 clks, + * then tri-state. */ +#define S626_EOS 0x00000001 /* End of superframe. */ + +/* I2C configuration constants. */ +#define S626_I2C_CLKSEL 0x0400 /* I2C bit rate = + * PCIclk/480 = 68.75 KHz. */ +#define S626_I2C_BITRATE 68.75 /* I2C bus data bit rate + * (determined by + * S626_I2C_CLKSEL) in KHz. */ +#define S626_I2C_WRTIME 15.0 /* Worst case time, in msec, + * for EEPROM internal write + * op. */ + +/* I2C manifest constants. */ + +/* Max retries to wait for EEPROM write. */ +#define S626_I2C_RETRIES (S626_I2C_WRTIME * S626_I2C_BITRATE / 9.0) +#define S626_I2C_ERR 0x0002 /* I2C control/status flag ERROR. */ +#define S626_I2C_BUSY 0x0001 /* I2C control/status flag BUSY. */ +#define S626_I2C_ABORT 0x0080 /* I2C status flag ABORT. */ +#define S626_I2C_ATTRSTART 0x3 /* I2C attribute START. */ +#define S626_I2C_ATTRCONT 0x2 /* I2C attribute CONT. */ +#define S626_I2C_ATTRSTOP 0x1 /* I2C attribute STOP. */ +#define S626_I2C_ATTRNOP 0x0 /* I2C attribute NOP. */ + +/* Code macros used for constructing I2C command bytes. */ +#define S626_I2C_B2(ATTR, VAL) (((ATTR) << 6) | ((VAL) << 24)) +#define S626_I2C_B1(ATTR, VAL) (((ATTR) << 4) | ((VAL) << 16)) +#define S626_I2C_B0(ATTR, VAL) (((ATTR) << 2) | ((VAL) << 8)) + +/* DEBI command constants. */ +#define S626_DEBI_CMD_SIZE16 (2 << 17) /* Transfer size is always + * 2 bytes. */ +#define S626_DEBI_CMD_READ 0x00010000 /* Read operation. */ +#define S626_DEBI_CMD_WRITE 0x00000000 /* Write operation. */ + +/* Read immediate 2 bytes. */ +#define S626_DEBI_CMD_RDWORD (S626_DEBI_CMD_READ | S626_DEBI_CMD_SIZE16) + +/* Write immediate 2 bytes. */ +#define S626_DEBI_CMD_WRWORD (S626_DEBI_CMD_WRITE | S626_DEBI_CMD_SIZE16) + +/* DEBI configuration constants. */ +#define S626_DEBI_CFG_XIRQ_EN 0x80000000 /* Enable external interrupt + * on GPIO3. */ +#define S626_DEBI_CFG_XRESUME 0x40000000 /* Resume block */ + /* Transfer when XIRQ + * deasserted. */ +#define S626_DEBI_CFG_TOQ 0x03C00000 /* Timeout (15 PCI cycles). */ +#define S626_DEBI_CFG_FAST 0x10000000 /* Fast mode enable. */ + +/* 4-bit field that specifies DEBI timeout value in PCI clock cycles: */ +#define S626_DEBI_CFG_TOUT_BIT 22 /* Finish DEBI cycle after this many + * clocks. */ + +/* 2-bit field that specifies Endian byte lane steering: */ +#define S626_DEBI_CFG_SWAP_NONE 0x00000000 /* Straight - don't swap any + * bytes (Intel). */ +#define S626_DEBI_CFG_SWAP_2 0x00100000 /* 2-byte swap (Motorola). */ +#define S626_DEBI_CFG_SWAP_4 0x00200000 /* 4-byte swap. */ +#define S626_DEBI_CFG_SLAVE16 0x00080000 /* Slave is able to serve + * 16-bit cycles. */ +#define S626_DEBI_CFG_INC 0x00040000 /* Enable address increment + * for block transfers. */ +#define S626_DEBI_CFG_INTEL 0x00020000 /* Intel style local bus. */ +#define S626_DEBI_CFG_TIMEROFF 0x00010000 /* Disable timer. */ + +#if S626_PLATFORM == S626_INTEL + +#define S626_DEBI_TOUT 7 /* Wait 7 PCI clocks (212 ns) before + * polling RDY. */ + +/* Intel byte lane steering (pass through all byte lanes). */ +#define S626_DEBI_SWAP S626_DEBI_CFG_SWAP_NONE + +#elif S626_PLATFORM == S626_MOTOROLA + +#define S626_DEBI_TOUT 15 /* Wait 15 PCI clocks (454 ns) maximum + * before timing out. */ + +/* Motorola byte lane steering. */ +#define S626_DEBI_SWAP S626_DEBI_CFG_SWAP_2 #endif -/* DEBI page table constants. */ -#define DEBI_PAGE_DISABLE 0x00000000 /* Paging disable. */ - -/* ******* 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. */ - -/* 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. */ - -/* 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. */ - -/* 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. */ - -/* 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. */ - -/* 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. */ - -#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. */ - -#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. */ - -#define NUM_COUNTERS 6 /* Maximum valid counter */ - /* logical channel number. */ -#define NUM_INTSOURCES 4 -#define NUM_LATCHSOURCES 4 -#define NUM_CLKMULTS 4 -#define NUM_CLKSOURCES 4 -#define NUM_CLKPOLS 2 -#define NUM_INDEXPOLS 2 -#define NUM_INDEXSOURCES 2 -#define NUM_LOADTRIGS 4 - -/* 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 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. */ - -#define CRAMSK_INDXSRC_B (3 << CRABIT_INDXSRC_B) -#define CRAMSK_CLKSRC_B (3 << CRABIT_CLKSRC_B) -#define CRAMSK_INDXPOL_A (1 << CRABIT_INDXPOL_A) -#define CRAMSK_LOADSRC_A (3 << CRABIT_LOADSRC_A) -#define CRAMSK_CLKMULT_A (3 << CRABIT_CLKMULT_A) -#define CRAMSK_INTSRC_A (3 << CRABIT_INTSRC_A) -#define CRAMSK_CLKPOL_A (3 << CRABIT_CLKPOL_A) -#define CRAMSK_INDXSRC_A (3 << CRABIT_INDXSRC_A) -#define CRAMSK_CLKSRC_A (3 << CRABIT_CLKSRC_A) - -#define CRBMSK_INTRESETCMD (1 << CRBBIT_INTRESETCMD) -#define CRBMSK_INTRESET_B (1 << CRBBIT_INTRESET_B) -#define CRBMSK_INTRESET_A (1 << CRBBIT_INTRESET_A) -#define CRBMSK_CLKENAB_A (1 << CRBBIT_CLKENAB_A) -#define CRBMSK_INTSRC_B (3 << CRBBIT_INTSRC_B) -#define CRBMSK_LATCHSRC (3 << CRBBIT_LATCHSRC) -#define CRBMSK_LOADSRC_B (3 << CRBBIT_LOADSRC_B) -#define CRBMSK_CLKMULT_B (3 << CRBBIT_CLKMULT_B) -#define CRBMSK_CLKENAB_B (1 << CRBBIT_CLKENAB_B) -#define CRBMSK_INDXPOL_B (1 << CRBBIT_INDXPOL_B) -#define CRBMSK_CLKPOL_B (1 << CRBBIT_CLKPOL_B) - -#define CRBMSK_INTCTRL (CRBMSK_INTRESETCMD | CRBMSK_INTRESET_A | CRBMSK_INTRESET_B) /* Interrupt reset control bits. */ - -/* Bit field positions for standardized SETUP structure. */ - -#define STDBIT_INTSRC 13 -#define STDBIT_LATCHSRC 11 -#define STDBIT_LOADSRC 9 -#define STDBIT_INDXSRC 7 -#define STDBIT_INDXPOL 6 -#define STDBIT_CLKSRC 4 -#define STDBIT_CLKPOL 3 -#define STDBIT_CLKMULT 1 -#define STDBIT_CLKENAB 0 - -/* Bit field masks for standardized SETUP structure. */ - -#define STDMSK_INTSRC (3 << STDBIT_INTSRC) -#define STDMSK_LATCHSRC (3 << STDBIT_LATCHSRC) -#define STDMSK_LOADSRC (3 << STDBIT_LOADSRC) -#define STDMSK_INDXSRC (1 << STDBIT_INDXSRC) -#define STDMSK_INDXPOL (1 << STDBIT_INDXPOL) -#define STDMSK_CLKSRC (3 << STDBIT_CLKSRC) -#define STDMSK_CLKPOL (1 << STDBIT_CLKPOL) -#define STDMSK_CLKMULT (3 << STDBIT_CLKMULT) -#define STDMSK_CLKENAB (1 << STDBIT_CLKENAB) - -struct bufferDMA { - dma_addr_t PhysicalBase; - void *LogicalBase; - uint32_t DMAHandle; -}; +/* DEBI page table constants. */ +#define S626_DEBI_PAGE_DISABLE 0x00000000 /* Paging disable. */ + +/* ******* EXTRA FROM OTHER SENSORAY * .h ******* */ + +/* LoadSrc values: */ +#define S626_LOADSRC_INDX 0 /* Preload core in response to Index. */ +#define S626_LOADSRC_OVER 1 /* Preload core in response to + * Overflow. */ +#define S626_LOADSRCB_OVERA 2 /* Preload B core in response to + * A Overflow. */ +#define S626_LOADSRC_NONE 3 /* Never preload core. */ + +/* IntSrc values: */ +#define S626_INTSRC_NONE 0 /* Interrupts disabled. */ +#define S626_INTSRC_OVER 1 /* Interrupt on Overflow. */ +#define S626_INTSRC_INDX 2 /* Interrupt on Index. */ +#define S626_INTSRC_BOTH 3 /* Interrupt on Index or Overflow. */ + +/* LatchSrc values: */ +#define S626_LATCHSRC_AB_READ 0 /* Latch on read. */ +#define S626_LATCHSRC_A_INDXA 1 /* Latch A on A Index. */ +#define S626_LATCHSRC_B_INDXB 2 /* Latch B on B Index. */ +#define S626_LATCHSRC_B_OVERA 3 /* Latch B on A Overflow. */ + +/* IndxSrc values: */ +#define S626_INDXSRC_HARD 0 /* Hardware or software index. */ +#define S626_INDXSRC_SOFT 1 /* Software index only. */ + +/* IndxPol values: */ +#define S626_INDXPOL_POS 0 /* Index input is active high. */ +#define S626_INDXPOL_NEG 1 /* Index input is active low. */ + +/* ClkSrc values: */ +#define S626_CLKSRC_COUNTER 0 /* Counter mode. */ +#define S626_CLKSRC_TIMER 2 /* Timer mode. */ +#define S626_CLKSRC_EXTENDER 3 /* Extender mode. */ + +/* ClkPol values: */ +#define S626_CLKPOL_POS 0 /* Counter/Extender clock is + * active high. */ +#define S626_CLKPOL_NEG 1 /* Counter/Extender clock is + * active low. */ +#define S626_CNTDIR_UP 0 /* Timer counts up. */ +#define S626_CNTDIR_DOWN 1 /* Timer counts down. */ + +/* ClkEnab values: */ +#define S626_CLKENAB_ALWAYS 0 /* Clock always enabled. */ +#define S626_CLKENAB_INDEX 1 /* Clock is enabled by index. */ + +/* ClkMult values: */ +#define S626_CLKMULT_4X 0 /* 4x clock multiplier. */ +#define S626_CLKMULT_2X 1 /* 2x clock multiplier. */ +#define S626_CLKMULT_1X 2 /* 1x clock multiplier. */ + +/* Bit Field positions in COUNTER_SETUP structure: */ +#define S626_BF_LOADSRC 9 /* Preload trigger. */ +#define S626_BF_INDXSRC 7 /* Index source. */ +#define S626_BF_INDXPOL 6 /* Index polarity. */ +#define S626_BF_CLKSRC 4 /* Clock source. */ +#define S626_BF_CLKPOL 3 /* Clock polarity/count direction. */ +#define S626_BF_CLKMULT 1 /* Clock multiplier. */ +#define S626_BF_CLKENAB 0 /* Clock enable. */ + +/* Enumerated counter clock multipliers. */ + +#define S626_MULT_X0 0x0003 /* Supports no multipliers; + * fixed physical multiplier = 3. */ +#define S626_MULT_X1 0x0002 /* Supports multiplier x1; + * fixed physical multiplier = 2. */ +#define S626_MULT_X2 0x0001 /* Supports multipliers x1, x2; + * physical multipliers = 1 or 2. */ +#define S626_MULT_X4 0x0000 /* Supports multipliers x1, x2, x4; + * physical multipliers = 0, 1 or 2. */ + +/* Sanity-check limits for parameters. */ + +#define S626_NUM_COUNTERS 6 /* Maximum valid counter + * logical channel number. */ +#define S626_NUM_INTSOURCES 4 +#define S626_NUM_LATCHSOURCES 4 +#define S626_NUM_CLKMULTS 4 +#define S626_NUM_CLKSOURCES 4 +#define S626_NUM_CLKPOLS 2 +#define S626_NUM_INDEXPOLS 2 +#define S626_NUM_INDEXSOURCES 2 +#define S626_NUM_LOADTRIGS 4 + +/* Bit field positions in CRA and CRB counter control registers. */ + +/* Bit field positions in CRA: */ +#define S626_CRABIT_INDXSRC_B 14 /* B index source. */ +#define S626_CRABIT_CLKSRC_B 12 /* B clock source. */ +#define S626_CRABIT_INDXPOL_A 11 /* A index polarity. */ +#define S626_CRABIT_LOADSRC_A 9 /* A preload trigger. */ +#define S626_CRABIT_CLKMULT_A 7 /* A clock multiplier. */ +#define S626_CRABIT_INTSRC_A 5 /* A interrupt source. */ +#define S626_CRABIT_CLKPOL_A 4 /* A clock polarity. */ +#define S626_CRABIT_INDXSRC_A 2 /* A index source. */ +#define S626_CRABIT_CLKSRC_A 0 /* A clock source. */ + +/* Bit field positions in CRB: */ +#define S626_CRBBIT_INTRESETCMD 15 /* Interrupt reset command. */ +#define S626_CRBBIT_INTRESET_B 14 /* B interrupt reset enable. */ +#define S626_CRBBIT_INTRESET_A 13 /* A interrupt reset enable. */ +#define S626_CRBBIT_CLKENAB_A 12 /* A clock enable. */ +#define S626_CRBBIT_INTSRC_B 10 /* B interrupt source. */ +#define S626_CRBBIT_LATCHSRC 8 /* A/B latch source. */ +#define S626_CRBBIT_LOADSRC_B 6 /* B preload trigger. */ +#define S626_CRBBIT_CLKMULT_B 3 /* B clock multiplier. */ +#define S626_CRBBIT_CLKENAB_B 2 /* B clock enable. */ +#define S626_CRBBIT_INDXPOL_B 1 /* B index polarity. */ +#define S626_CRBBIT_CLKPOL_B 0 /* B clock polarity. */ + +/* Bit field masks for CRA and CRB. */ + +#define S626_CRAMSK_INDXSRC_B (3 << S626_CRABIT_INDXSRC_B) +#define S626_CRAMSK_CLKSRC_B (3 << S626_CRABIT_CLKSRC_B) +#define S626_CRAMSK_INDXPOL_A (1 << S626_CRABIT_INDXPOL_A) +#define S626_CRAMSK_LOADSRC_A (3 << S626_CRABIT_LOADSRC_A) +#define S626_CRAMSK_CLKMULT_A (3 << S626_CRABIT_CLKMULT_A) +#define S626_CRAMSK_INTSRC_A (3 << S626_CRABIT_INTSRC_A) +#define S626_CRAMSK_CLKPOL_A (3 << S626_CRABIT_CLKPOL_A) +#define S626_CRAMSK_INDXSRC_A (3 << S626_CRABIT_INDXSRC_A) +#define S626_CRAMSK_CLKSRC_A (3 << S626_CRABIT_CLKSRC_A) + +#define S626_CRBMSK_INTRESETCMD (1 << S626_CRBBIT_INTRESETCMD) +#define S626_CRBMSK_INTRESET_B (1 << S626_CRBBIT_INTRESET_B) +#define S626_CRBMSK_INTRESET_A (1 << S626_CRBBIT_INTRESET_A) +#define S626_CRBMSK_CLKENAB_A (1 << S626_CRBBIT_CLKENAB_A) +#define S626_CRBMSK_INTSRC_B (3 << S626_CRBBIT_INTSRC_B) +#define S626_CRBMSK_LATCHSRC (3 << S626_CRBBIT_LATCHSRC) +#define S626_CRBMSK_LOADSRC_B (3 << S626_CRBBIT_LOADSRC_B) +#define S626_CRBMSK_CLKMULT_B (3 << S626_CRBBIT_CLKMULT_B) +#define S626_CRBMSK_CLKENAB_B (1 << S626_CRBBIT_CLKENAB_B) +#define S626_CRBMSK_INDXPOL_B (1 << S626_CRBBIT_INDXPOL_B) +#define S626_CRBMSK_CLKPOL_B (1 << S626_CRBBIT_CLKPOL_B) + +/* Interrupt reset control bits. */ +#define S626_CRBMSK_INTCTRL (S626_CRBMSK_INTRESETCMD | \ + S626_CRBMSK_INTRESET_A | \ + S626_CRBMSK_INTRESET_B) + +/* Bit field positions for standardized SETUP structure. */ + +#define S626_STDBIT_INTSRC 13 +#define S626_STDBIT_LATCHSRC 11 +#define S626_STDBIT_LOADSRC 9 +#define S626_STDBIT_INDXSRC 7 +#define S626_STDBIT_INDXPOL 6 +#define S626_STDBIT_CLKSRC 4 +#define S626_STDBIT_CLKPOL 3 +#define S626_STDBIT_CLKMULT 1 +#define S626_STDBIT_CLKENAB 0 + +/* Bit field masks for standardized SETUP structure. */ + +#define S626_STDMSK_INTSRC (3 << S626_STDBIT_INTSRC) +#define S626_STDMSK_LATCHSRC (3 << S626_STDBIT_LATCHSRC) +#define S626_STDMSK_LOADSRC (3 << S626_STDBIT_LOADSRC) +#define S626_STDMSK_INDXSRC (1 << S626_STDBIT_INDXSRC) +#define S626_STDMSK_INDXPOL (1 << S626_STDBIT_INDXPOL) +#define S626_STDMSK_CLKSRC (3 << S626_STDBIT_CLKSRC) +#define S626_STDMSK_CLKPOL (1 << S626_STDBIT_CLKPOL) +#define S626_STDMSK_CLKMULT (3 << S626_STDBIT_CLKMULT) +#define S626_STDMSK_CLKENAB (1 << S626_STDBIT_CLKENAB) + +#endif diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 9218d7336923..da1d501d9e4e 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -122,7 +122,7 @@ sampling rate. If you sample two channels you get 4kHz and so on. #define PWM_DEFAULT_PERIOD ((long)(1E9/100)) /* Size of one A/D value */ -#define SIZEADIN ((sizeof(int16_t))) +#define SIZEADIN ((sizeof(uint16_t))) /* * Size of the input-buffer IN BYTES @@ -134,7 +134,7 @@ sampling rate. If you sample two channels you get 4kHz and so on. #define SIZEINSNBUF 16 /* size of one value for the D/A converter: channel and value */ -#define SIZEDAOUT ((sizeof(int8_t)+sizeof(int16_t))) +#define SIZEDAOUT ((sizeof(uint8_t)+sizeof(uint16_t))) /* * Size of the output-buffer in bytes @@ -195,15 +195,15 @@ struct usbdux_private { /* PWM period */ unsigned int pwm_period; /* PWM internal delay for the GPIF in the FX2 */ - int8_t pwm_delay; + uint8_t pwm_delay; /* size of the PWM buffer which holds the bit pattern */ int pwm_buf_sz; /* input buffer for the ISO-transfer */ - int16_t *in_buf; + uint16_t *in_buf; /* input buffer for single insn */ - int16_t *insn_buf; + uint16_t *insn_buf; - int8_t ao_chanlist[USBDUX_NUM_AO_CHAN]; + uint8_t ao_chanlist[USBDUX_NUM_AO_CHAN]; unsigned int ao_readback[USBDUX_NUM_AO_CHAN]; unsigned int high_speed:1; @@ -225,7 +225,7 @@ struct usbdux_private { /* interval in frames/uframes */ unsigned int ai_interval; /* commands */ - int8_t *dux_commands; + uint8_t *dux_commands; struct semaphore sem; }; @@ -367,7 +367,7 @@ static void usbduxsub_ai_isoc_irq(struct urb *urb) n = s->async->cmd.chanlist_len; for (i = 0; i < n; i++) { unsigned int range = CR_RANGE(s->async->cmd.chanlist[i]); - int16_t val = le16_to_cpu(devpriv->in_buf[i]); + uint16_t val = le16_to_cpu(devpriv->in_buf[i]); /* bipolar data is two's-complement */ if (comedi_range_is_bipolar(s, range)) @@ -415,7 +415,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) struct comedi_device *dev = urb->context; struct comedi_subdevice *s = dev->write_subdev; struct usbdux_private *devpriv = dev->private; - int8_t *datap; + uint8_t *datap; int len; int ret; int i; @@ -483,7 +483,7 @@ static void usbduxsub_ao_isoc_irq(struct urb *urb) *datap++ = len; for (i = 0; i < s->async->cmd.chanlist_len; i++) { unsigned int chan = devpriv->ao_chanlist[i]; - short val; + unsigned short val; ret = comedi_buf_get(s->async, &val); if (ret < 0) { @@ -649,14 +649,15 @@ static int usbdux_ai_cmdtest(struct comedi_device *dev, * creates the ADC command for the MAX1271 * range is the range value from comedi */ -static int8_t create_adc_command(unsigned int chan, int range) +static uint8_t create_adc_command(unsigned int chan, unsigned int range) { - int8_t p = (range <= 1); - int8_t r = ((range % 2) == 0); + uint8_t p = (range <= 1); + uint8_t r = ((range % 2) == 0); + return (chan << 4) | ((p == 1) << 2) | ((r == 1) << 3); } -static int send_dux_commands(struct comedi_device *dev, int cmd_type) +static int send_dux_commands(struct comedi_device *dev, unsigned int cmd_type) { struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv = dev->private; @@ -669,7 +670,7 @@ static int send_dux_commands(struct comedi_device *dev, int cmd_type) &nsent, BULK_TIMEOUT); } -static int receive_dux_commands(struct comedi_device *dev, int command) +static int receive_dux_commands(struct comedi_device *dev, unsigned int command) { struct usb_device *usb = comedi_to_usb_dev(dev); struct usbdux_private *devpriv = dev->private; @@ -879,7 +880,7 @@ static int usbdux_ao_insn_write(struct comedi_device *dev, struct usbdux_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int val = devpriv->ao_readback[chan]; - int16_t *p = (int16_t *)&devpriv->dux_commands[2]; + uint16_t *p = (uint16_t *)&devpriv->dux_commands[2]; int ret = -EBUSY; int i; @@ -1198,7 +1199,7 @@ static int usbdux_counter_write(struct comedi_device *dev, { struct usbdux_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - int16_t *p = (int16_t *)&devpriv->dux_commands[2]; + uint16_t *p = (uint16_t *)&devpriv->dux_commands[2]; int ret = 0; int i; diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 5618e61893da..a5363ded3668 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -78,7 +78,7 @@ #define USBDUXSIGMA_NUM_AO_CHAN 4 /* Size of one A/D value */ -#define SIZEADIN ((sizeof(int32_t))) +#define SIZEADIN ((sizeof(uint32_t))) /* * Size of the async input-buffer IN BYTES, the DIO state is transmitted @@ -93,7 +93,7 @@ #define NUMOUTCHANNELS 8 /* size of one value for the D/A converter: channel and value */ -#define SIZEDAOUT ((sizeof(uint8_t)+sizeof(int16_t))) +#define SIZEDAOUT ((sizeof(uint8_t)+sizeof(uint16_t))) /* * Size of the output-buffer in bytes @@ -157,11 +157,11 @@ struct usbduxsigma_private { /* size of the PWM buffer which holds the bit pattern */ int pwm_buf_sz; /* input buffer for the ISO-transfer */ - int32_t *in_buf; + uint32_t *in_buf; /* input buffer for single insn */ - int8_t *insn_buf; + uint8_t *insn_buf; - int8_t ao_chanlist[USBDUXSIGMA_NUM_AO_CHAN]; + uint8_t ao_chanlist[USBDUXSIGMA_NUM_AO_CHAN]; unsigned int ao_readback[USBDUXSIGMA_NUM_AO_CHAN]; unsigned high_speed:1; @@ -224,7 +224,7 @@ static void usbduxsigma_ai_urb_complete(struct urb *urb) struct usbduxsigma_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned int dio_state; - int32_t val; + uint32_t val; int ret; int i; @@ -421,7 +421,7 @@ static void usbduxsigma_ao_urb_complete(struct urb *urb) *datap++ = len; for (i = 0; i < len; i++) { unsigned int chan = devpriv->ao_chanlist[i]; - short val; + unsigned short val; ret = comedi_buf_get(s->async, &val); if (ret < 0) { @@ -784,7 +784,7 @@ static int usbduxsigma_ai_insn_read(struct comedi_device *dev, } for (i = 0; i < insn->n; i++) { - int32_t val; + uint32_t val; ret = usbduxsigma_receive_cmd(dev, USBDUXSIGMA_SINGLE_AD_CMD); if (ret < 0) { @@ -793,7 +793,7 @@ static int usbduxsigma_ai_insn_read(struct comedi_device *dev, } /* 32 bits big endian from the A/D converter */ - val = be32_to_cpu(*((int32_t *)((devpriv->insn_buf) + 1))); + val = be32_to_cpu(*((uint32_t *)((devpriv->insn_buf) + 1))); val &= 0x00ffffff; /* strip status byte */ val ^= 0x00800000; /* convert to unsigned */ @@ -1358,7 +1358,7 @@ static int usbduxsigma_getstatusinfo(struct comedi_device *dev, int chan) return ret; /* 32 bits big endian from the A/D converter */ - val = be32_to_cpu(*((int32_t *)((devpriv->insn_buf)+1))); + val = be32_to_cpu(*((uint32_t *)((devpriv->insn_buf)+1))); val &= 0x00ffffff; /* strip status byte */ val ^= 0x00800000; /* convert to unsigned */ diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c index b17fbf8181cf..190b9b924368 100644 --- a/drivers/staging/crystalhd/crystalhd_lnx.c +++ b/drivers/staging/crystalhd/crystalhd_lnx.c @@ -75,8 +75,9 @@ static int chd_dec_disable_int(struct crystalhd_adp *adp) return 0; } -struct crystalhd_ioctl_data *chd_dec_alloc_iodata(struct crystalhd_adp *adp, - bool isr) +static struct +crystalhd_ioctl_data *chd_dec_alloc_iodata(struct crystalhd_adp *adp, + bool isr) { unsigned long flags = 0; struct crystalhd_ioctl_data *temp; @@ -96,8 +97,8 @@ struct crystalhd_ioctl_data *chd_dec_alloc_iodata(struct crystalhd_adp *adp, return temp; } -void chd_dec_free_iodata(struct crystalhd_adp *adp, - struct crystalhd_ioctl_data *iodata, bool isr) +static void chd_dec_free_iodata(struct crystalhd_adp *adp, + struct crystalhd_ioctl_data *iodata, bool isr) { unsigned long flags = 0; @@ -156,7 +157,7 @@ static int chd_dec_fetch_cdata(struct crystalhd_adp *adp, if (rc) { BCMLOG_ERR("failed to pull add_cdata sz:%x ua_off:%x\n", io->add_cdata_sz, (unsigned int)ua_off); - kfree(io->add_cdata); + vfree(io->add_cdata); io->add_cdata = NULL; return -ENODATA; } @@ -627,7 +628,7 @@ err: } #ifdef CONFIG_PM -int chd_dec_pci_suspend(struct pci_dev *pdev, pm_message_t state) +static int chd_dec_pci_suspend(struct pci_dev *pdev, pm_message_t state) { struct crystalhd_adp *adp; struct crystalhd_ioctl_data *temp; @@ -661,7 +662,7 @@ int chd_dec_pci_suspend(struct pci_dev *pdev, pm_message_t state) return 0; } -int chd_dec_pci_resume(struct pci_dev *pdev) +static int chd_dec_pci_resume(struct pci_dev *pdev) { struct crystalhd_adp *adp; enum BC_STATUS sts = BC_STS_SUCCESS; diff --git a/drivers/staging/cxt1e1/comet.c b/drivers/staging/cxt1e1/comet.c index 8cef283102ee..46a0d92173e0 100644 --- a/drivers/staging/cxt1e1/comet.c +++ b/drivers/staging/cxt1e1/comet.c @@ -145,8 +145,7 @@ void init_comet(void *ci, comet_t *comet, u_int32_t port_mode, int clockmaster, /* Enable 8 out of 10 validation */ /* t1RBOC enable(BOC:BitOriented Code) */ pci_write_32((u_int32_t *) &comet->t1_rboc_ena, 0x00); - if (isT1mode) - { + if (isT1mode) { /* IBCD cfg: aka Inband Code Detection ** loopback code length set to */ /* 6 bit down, 5 bit up (assert) */ pci_write_32((u_int32_t *) &comet->ibcd_cfg, 0x04); diff --git a/drivers/staging/cxt1e1/comet.h b/drivers/staging/cxt1e1/comet.h index e06da4a6f6f6..03b9bb77a809 100644 --- a/drivers/staging/cxt1e1/comet.h +++ b/drivers/staging/cxt1e1/comet.h @@ -338,7 +338,7 @@ typedef struct s_comet_reg comet_t; #ifdef __KERNEL__ extern void -init_comet (void *, comet_t *, u_int32_t, int, u_int8_t); +init_comet(void *, comet_t *, u_int32_t, int, u_int8_t); #endif #endif /* _INC_COMET_H_ */ diff --git a/drivers/staging/cxt1e1/sbew_ioc.h b/drivers/staging/cxt1e1/sbew_ioc.h index ce9b15c71894..e1e5bfc9ad37 100644 --- a/drivers/staging/cxt1e1/sbew_ioc.h +++ b/drivers/staging/cxt1e1/sbew_ioc.h @@ -39,21 +39,21 @@ */ #define SBE_IOC_LOGLEVEL _IOW(SBE_IOC_MAGIC, 0x00, int) -#define SBE_IOC_CHAN_NEW _IOW(SBE_IOC_MAGIC, 0x01,int) /* unused */ -#define SBE_IOC_CHAN_UP _IOW(SBE_IOC_MAGIC, 0x02,int) /* unused */ -#define SBE_IOC_CHAN_DOWN _IOW(SBE_IOC_MAGIC, 0x03,int) /* unused */ -#define SBE_IOC_CHAN_GET _IOWR(SBE_IOC_MAGIC,0x04, struct sbecom_chan_param) +#define SBE_IOC_CHAN_NEW _IOW(SBE_IOC_MAGIC, 0x01, int) /* unused */ +#define SBE_IOC_CHAN_UP _IOW(SBE_IOC_MAGIC, 0x02, int) /* unused */ +#define SBE_IOC_CHAN_DOWN _IOW(SBE_IOC_MAGIC, 0x03, int) /* unused */ +#define SBE_IOC_CHAN_GET _IOWR(SBE_IOC_MAGIC, 0x04, struct sbecom_chan_param) #define SBE_IOC_CHAN_SET _IOW(SBE_IOC_MAGIC, 0x05, struct sbecom_chan_param) -#define SBE_IOC_CHAN_GET_STAT _IOWR(SBE_IOC_MAGIC,0x06, struct sbecom_chan_stats) +#define SBE_IOC_CHAN_GET_STAT _IOWR(SBE_IOC_MAGIC, 0x06, struct sbecom_chan_stats) #define SBE_IOC_CHAN_DEL_STAT _IOW(SBE_IOC_MAGIC, 0x07, int) #define SBE_IOC_PORTS_ENABLE _IOW(SBE_IOC_MAGIC, 0x0A, int) -#define SBE_IOC_PORT_GET _IOWR(SBE_IOC_MAGIC,0x0C, struct sbecom_port_param) +#define SBE_IOC_PORT_GET _IOWR(SBE_IOC_MAGIC, 0x0C, struct sbecom_port_param) #define SBE_IOC_PORT_SET _IOW(SBE_IOC_MAGIC, 0x0D, struct sbecom_port_param) -#define SBE_IOC_READ_VEC _IOWR(SBE_IOC_MAGIC,0x10, struct sbecom_wrt_vec) -#define SBE_IOC_WRITE_VEC _IOWR(SBE_IOC_MAGIC,0x11, struct sbecom_wrt_vec) +#define SBE_IOC_READ_VEC _IOWR(SBE_IOC_MAGIC, 0x10, struct sbecom_wrt_vec) +#define SBE_IOC_WRITE_VEC _IOWR(SBE_IOC_MAGIC, 0x11, struct sbecom_wrt_vec) #define SBE_IOC_GET_SN _IOR(SBE_IOC_MAGIC, 0x12, u_int32_t) #define SBE_IOC_RESET_DEV _IOW(SBE_IOC_MAGIC, 0x13, int) -#define SBE_IOC_FRAMER_GET _IOWR(SBE_IOC_MAGIC,0x14, struct sbecom_framer_param) +#define SBE_IOC_FRAMER_GET _IOWR(SBE_IOC_MAGIC, 0x14, struct sbecom_framer_param) #define SBE_IOC_FRAMER_SET _IOW(SBE_IOC_MAGIC, 0x15, struct sbecom_framer_param) #define SBE_IOC_CARD_GET _IOR(SBE_IOC_MAGIC, 0x20, struct sbecom_card_param) #define SBE_IOC_CARD_SET _IOW(SBE_IOC_MAGIC, 0x21, struct sbecom_card_param) @@ -61,13 +61,13 @@ #define SBE_IOC_CARD_DEL_STAT _IO(SBE_IOC_MAGIC, 0x23) #define SBE_IOC_CARD_CHAN_STAT _IOR(SBE_IOC_MAGIC, 0x24, struct sbecom_chan_stats) #define SBE_IOC_CARD_BLINK _IOW(SBE_IOC_MAGIC, 0x30, int) -#define SBE_IOC_DRVINFO_GET _IOWR(SBE_IOC_MAGIC,0x31, struct sbe_drv_info) +#define SBE_IOC_DRVINFO_GET _IOWR(SBE_IOC_MAGIC, 0x31, struct sbe_drv_info) #define SBE_IOC_BRDINFO_GET _IOR(SBE_IOC_MAGIC, 0x32, struct sbe_brd_info) -#define SBE_IOC_IID_GET _IOWR(SBE_IOC_MAGIC,0x33, struct sbe_iid_info) +#define SBE_IOC_IID_GET _IOWR(SBE_IOC_MAGIC, 0x33, struct sbe_iid_info) #define SBE_IOC_BRDADDR_GET _IOWR(SBE_IOC_MAGIC, 0x34, struct sbe_brd_addr) #ifdef NOT_YET_COMMON -#define SBE_IOC_TSIOC_GET _IOWR(SBE_IOC_MAGIC,0x16, struct wanc1t3_ts_param) +#define SBE_IOC_TSIOC_GET _IOWR(SBE_IOC_MAGIC, 0x16, struct wanc1t3_ts_param) #define SBE_IOC_TSIOC_SET _IOW(SBE_IOC_MAGIC, 0x17, struct wanc1t3_ts_param) #endif diff --git a/drivers/staging/dgap/dgap_fep5.c b/drivers/staging/dgap/dgap_fep5.c index 4464f02c9575..794cf9db8b83 100644 --- a/drivers/staging/dgap/dgap_fep5.c +++ b/drivers/staging/dgap/dgap_fep5.c @@ -134,7 +134,7 @@ int dgap_after_config_loaded(void) dgap_Board[i]->flipflagbuf = dgap_driver_kzmalloc(MYFLIPLEN, GFP_ATOMIC); } - return (rc); + return rc; } @@ -150,14 +150,14 @@ static int dgap_usertoboard(struct board_t *brd, char *to_addr, char __user *fro int n = U2BSIZE; if (!brd || brd->magic != DGAP_BOARD_MAGIC) - return(-EFAULT); + return -EFAULT; while (len) { if (n > len) n = len; if (copy_from_user((char *) &buf, from_addr, n) == -1 ) { - return(-EFAULT); + return -EFAULT; } /* Copy data from buffer to card memory */ @@ -169,7 +169,7 @@ static int dgap_usertoboard(struct board_t *brd, char *to_addr, char __user *fro from_addr += n; n = U2BSIZE; } - return(0); + return 0; } @@ -1155,20 +1155,20 @@ uint dgap_get_custom_baud(struct channel_t *ch) uint value = 0; if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) { - return (0); + return 0; } if (!ch->ch_bd || ch->ch_bd->magic != DGAP_BOARD_MAGIC) { - return (0); + return 0; } if (!(ch->ch_bd->bd_flags & BD_FEP5PLUS)) - return (0); + return 0; vaddr = ch->ch_bd->re_map_membase; if (!vaddr) - return (0); + return 0; /* * Go get from fep mem, what the fep @@ -1178,7 +1178,7 @@ uint dgap_get_custom_baud(struct channel_t *ch) (ch->ch_portnum * 0x28) + LINE_SPEED)); value = readw(vaddr + offset); - return (value); + return value; } @@ -1229,29 +1229,24 @@ int dgap_param(struct tty_struct *tty) uchar mval; uchar hflow; - if (!tty || tty->magic != TTY_MAGIC) { - return (-ENXIO); - } + if (!tty || tty->magic != TTY_MAGIC) + return -ENXIO; un = (struct un_t *) tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) { - return (-ENXIO); - } + if (!un || un->magic != DGAP_UNIT_MAGIC) + return -ENXIO; ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) { - return (-ENXIO); - } + if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) + return -ENXIO; bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) { - return (-ENXIO); - } + if (!bd || bd->magic != DGAP_BOARD_MAGIC) + return -ENXIO; bs = ch->ch_bs; - if (bs == 0) { - return (-ENXIO); - } + if (!bs) + return -ENXIO; DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n", ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag)); @@ -1558,7 +1553,7 @@ int dgap_param(struct tty_struct *tty) DPR_PARAM(("param finish\n")); - return (0); + return 0; } @@ -1675,7 +1670,7 @@ static int dgap_event(struct board_t *bd) int b1; if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return (-ENXIO); + return -ENXIO; DGAP_LOCK(bd->bd_lock, lock_flags); @@ -1683,7 +1678,7 @@ static int dgap_event(struct board_t *bd) if (!vaddr) { DGAP_UNLOCK(bd->bd_lock, lock_flags); - return (-ENXIO); + return -ENXIO; } eaddr = (struct ev_t *) (vaddr + EVBUF); @@ -1701,7 +1696,7 @@ static int dgap_event(struct board_t *bd) DPR_EVENT(("should be calling xxfail %d\n", __LINE__)); /* Let go of board lock */ DGAP_UNLOCK(bd->bd_lock, lock_flags); - return (-ENXIO); + return -ENXIO; } /* @@ -1949,5 +1944,5 @@ next: writew(tail, &(eaddr->ev_tail)); DGAP_UNLOCK(bd->bd_lock, lock_flags); - return (0); + return 0; } diff --git a/drivers/staging/dgap/dgap_tty.c b/drivers/staging/dgap/dgap_tty.c index 924e2bfcbe30..2a7a37298da4 100644 --- a/drivers/staging/dgap/dgap_tty.c +++ b/drivers/staging/dgap/dgap_tty.c @@ -595,7 +595,7 @@ static void dgap_sniff_nowait_nolock(struct channel_t *ch, uchar *text, uchar *b /* * Loop while data remains. */ - while (nbuf > 0 && ch->ch_sniff_buf != 0) { + while (nbuf > 0 && ch->ch_sniff_buf) { /* * Determine the amount of available space left in the * buffer. If there's none, wait until some appears. @@ -1107,9 +1107,10 @@ static int dgap_tty_open(struct tty_struct *tty, struct file *file) MAJOR(tty_devnum(tty)), MINOR(tty_devnum(tty)), un, brd->name)); /* - * Error if channel info pointer is 0. + * Error if channel info pointer is NULL. */ - if ((bs = ch->ch_bs) == 0) { + bs = ch->ch_bs; + if (!bs) { DGAP_UNLOCK(ch->ch_lock, lock_flags2); DGAP_UNLOCK(brd->bd_lock, lock_flags); DPR_OPEN(("%d BS is 0!\n", __LINE__)); diff --git a/drivers/staging/dgnc/dgnc_cls.c b/drivers/staging/dgnc/dgnc_cls.c index fa1bb633f036..fdc1aabc7fde 100644 --- a/drivers/staging/dgnc/dgnc_cls.c +++ b/drivers/staging/dgnc/dgnc_cls.c @@ -33,7 +33,7 @@ #include <linux/sched.h> /* For jiffies, task states */ #include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */ #include <linux/delay.h> /* For udelay */ -#include <asm/io.h> /* For read[bwl]/write[bwl] */ +#include <linux/io.h> /* For read[bwl]/write[bwl] */ #include <linux/serial.h> /* For struct async_serial */ #include <linux/serial_reg.h> /* For the various UART offsets */ #include <linux/pci.h> @@ -417,9 +417,8 @@ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) isr = readb(&ch->ch_cls_uart->isr_fcr); /* Bail if no pending interrupt on port */ - if (isr & UART_IIR_NO_INT) { + if (isr & UART_IIR_NO_INT) break; - } DPR_INTR(("%s:%d port: %x isr: %x\n", __FILE__, __LINE__, port, isr)); @@ -444,9 +443,8 @@ static inline void cls_parse_isr(struct dgnc_board *brd, uint port) } /* Received Xoff signal/Special character */ - if (isr & UART_IIR_XOFF) { + if (isr & UART_IIR_XOFF) /* Empty */ - } /* CTS/RTS change of state */ if (isr & UART_IIR_CTSRTS) { @@ -481,24 +479,20 @@ static void cls_param(struct tty_struct *tty) struct channel_t *ch; struct un_t *un; - if (!tty || tty->magic != TTY_MAGIC) { + if (!tty || tty->magic != TTY_MAGIC) return; - } un = (struct un_t *) tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) { + if (!un || un->magic != DGNC_UNIT_MAGIC) return; - } ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) { + if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) return; - } bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) { + if (!bd || bd->magic != DGNC_BOARD_MAGIC) return; - } DPR_PARAM(("param start: tdev: %x cflags: %x oflags: %x iflags: %x\n", ch->ch_tun.un_dev, ch->ch_c_cflag, ch->ch_c_oflag, ch->ch_c_iflag)); @@ -1305,9 +1299,8 @@ static uint cls_get_uart_bytes_left(struct channel_t *ch) /* Determine whether the Transmitter is empty or not */ if (!(lsr & UART_LSR_TEMT)) { - if (ch->ch_flags & CH_TX_FIFO_EMPTY) { + if (ch->ch_flags & CH_TX_FIFO_EMPTY) tasklet_schedule(&ch->ch_bd->helper_tasklet); - } left = 1; } else { diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index c6fee11632f7..a6c6aba82d72 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -520,7 +520,7 @@ void dgnc_sniff_nowait_nolock(struct channel_t *ch, uchar *text, uchar *buf, int /* * Loop while data remains. */ - while (nbuf > 0 && ch->ch_sniff_buf != 0) { + while (nbuf > 0 && ch->ch_sniff_buf) { /* * Determine the amount of available space left in the * buffer. If there's none, wait until some appears. diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c index 5190c8ac4e0a..1a1413d31af6 100644 --- a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c +++ b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c @@ -1,12 +1,8 @@ -//===================================================== -// CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved. -// -// -// This file is part of Express Card USB Driver -// -// $Id: -//==================================================== -// 20090926; aelias; removed compiler warnings; ubuntu 9.04; 2.6.28-15-generic +/* +* CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved. +* +* This file is part of Express Card USB Driver +*/ #include <linux/init.h> #include <linux/kernel.h> @@ -111,19 +107,8 @@ struct dsp_image_info { }; -//--------------------------------------------------------------------------- -// Function: check_usb_db -// -// Parameters: struct ft1000_usb - device structure -// -// Returns: 0 - success -// -// Description: This function checks if the doorbell register is cleared -// -// Notes: -// -//--------------------------------------------------------------------------- -static u32 check_usb_db (struct ft1000_usb *ft1000dev) +/* checks if the doorbell register is cleared */ +static u32 check_usb_db(struct ft1000_usb *ft1000dev) { int loopcnt; u16 temp; @@ -169,20 +154,7 @@ static u32 check_usb_db (struct ft1000_usb *ft1000dev) return HANDSHAKE_MAG_TIMEOUT_VALUE; } -//--------------------------------------------------------------------------- -// Function: get_handshake -// -// Parameters: struct ft1000_usb - device structure -// u16 expected_value - the handshake value expected -// -// Returns: handshakevalue - success -// HANDSHAKE_TIMEOUT_VALUE - failure -// -// Description: This function gets the handshake and compare with the expected value -// -// Notes: -// -//--------------------------------------------------------------------------- +/* gets the handshake and compares it with the expected value */ static u16 get_handshake(struct ft1000_usb *ft1000dev, u16 expected_value) { u16 handshake; @@ -229,20 +201,7 @@ static u16 get_handshake(struct ft1000_usb *ft1000dev, u16 expected_value) return HANDSHAKE_TIMEOUT_VALUE; } -//--------------------------------------------------------------------------- -// Function: put_handshake -// -// Parameters: struct ft1000_usb - device structure -// u16 handshake_value - handshake to be written -// -// Returns: none -// -// Description: This function write the handshake value to the handshake location -// in DPRAM -// -// Notes: -// -//--------------------------------------------------------------------------- +/* write the handshake value to the handshake location */ static void put_handshake(struct ft1000_usb *ft1000dev,u16 handshake_value) { u32 tempx; @@ -316,18 +275,6 @@ static void put_handshake_usb(struct ft1000_usb *ft1000dev,u16 handshake_value) for (i=0; i<1000; i++); } -//--------------------------------------------------------------------------- -// Function: get_request_type -// -// Parameters: struct ft1000_usb - device structure -// -// Returns: request type - success -// -// Description: This function returns the request type -// -// Notes: -// -//--------------------------------------------------------------------------- static u16 get_request_type(struct ft1000_usb *ft1000dev) { u16 request_type; @@ -380,18 +327,6 @@ static u16 get_request_type_usb(struct ft1000_usb *ft1000dev) return request_type; } -//--------------------------------------------------------------------------- -// Function: get_request_value -// -// Parameters: struct ft1000_usb - device structure -// -// Returns: request value - success -// -// Description: This function returns the request value -// -// Notes: -// -//--------------------------------------------------------------------------- static long get_request_value(struct ft1000_usb *ft1000dev) { u32 value; @@ -416,19 +351,7 @@ static long get_request_value(struct ft1000_usb *ft1000dev) } -//--------------------------------------------------------------------------- -// Function: put_request_value -// -// Parameters: struct ft1000_usb - device structure -// long lvalue - value to be put into DPRAM location DWNLD_MAG1_SIZE_LOC -// -// Returns: none -// -// Description: This function writes a value to DWNLD_MAG1_SIZE_LOC -// -// Notes: -// -//--------------------------------------------------------------------------- +/* writes a value to DWNLD_MAG1_SIZE_LOC */ static void put_request_value(struct ft1000_usb *ft1000dev, long lvalue) { u32 tempx; @@ -441,18 +364,7 @@ static void put_request_value(struct ft1000_usb *ft1000dev, long lvalue) -//--------------------------------------------------------------------------- -// Function: hdr_checksum -// -// Parameters: struct pseudo_hdr *pHdr - Pseudo header pointer -// -// Returns: checksum - success -// -// Description: This function returns the checksum of the pseudo header -// -// Notes: -// -//--------------------------------------------------------------------------- +/* returns the checksum of the pseudo header */ static u16 hdr_checksum(struct pseudo_hdr *pHdr) { u16 *usPtr = (u16 *)pHdr; @@ -477,23 +389,12 @@ static int check_buffers(u16 *buff_w, u16 *buff_r, int len, int offset) return 0; } -//--------------------------------------------------------------------------- -// Function: write_blk -// -// Parameters: struct ft1000_usb - device structure -// u16 **pUsFile - DSP image file pointer in u16 -// u8 **pUcFile - DSP image file pointer in u8 -// long word_length - length of the buffer to be written -// to DPRAM -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function writes a block of DSP image to DPRAM -// -// Notes: -// -//--------------------------------------------------------------------------- +/* writes a block of DSP image to DPRAM + * Parameters: struct ft1000_usb - device structure + * u16 **pUsFile - DSP image file pointer in u16 + * u8 **pUcFile - DSP image file pointer in u8 + * long word_length - length of the buffer to be written to DPRAM + */ static u32 write_blk (struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile, long word_length) { u32 Status = STATUS_SUCCESS; @@ -616,23 +517,12 @@ static void usb_dnld_complete (struct urb *urb) //DEBUG("****** usb_dnld_complete\n"); } -//--------------------------------------------------------------------------- -// Function: write_blk_fifo -// -// Parameters: struct ft1000_usb - device structure -// u16 **pUsFile - DSP image file pointer in u16 -// u8 **pUcFile - DSP image file pointer in u8 -// long word_length - length of the buffer to be written -// to DPRAM -// -// Returns: STATUS_SUCCESS - success -// STATUS_FAILURE - failure -// -// Description: This function writes a block of DSP image to DPRAM -// -// Notes: -// -//--------------------------------------------------------------------------- +/* writes a block of DSP image to DPRAM + * Parameters: struct ft1000_usb - device structure + * u16 **pUsFile - DSP image file pointer in u16 + * u8 **pUcFile - DSP image file pointer in u8 + * long word_length - length of the buffer to be written to DPRAM + */ static u32 write_blk_fifo(struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile, long word_length) { @@ -664,18 +554,7 @@ static u32 write_blk_fifo(struct ft1000_usb *ft1000dev, u16 **pUsFile, return Status; } -//--------------------------------------------------------------------------- -// -// Function: scram_dnldr -// -// Synopsis: Scramble downloader for Harley based ASIC via USB interface -// -// Arguments: pFileStart - pointer to start of file -// FileLength - file length -// -// Returns: status - return code -//--------------------------------------------------------------------------- - +/* Scramble downloader for Harley based ASIC via USB interface */ u16 scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, u32 FileLength) { @@ -1036,7 +915,7 @@ u16 scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, status = fix_ft1000_write_dpram32 (ft1000dev, dpram++, - (u8 *) & templong); + (u8 *) &templong); } break; @@ -1137,13 +1016,13 @@ u16 scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, if (pseudo_header->checksum == hdr_checksum(pseudo_header)) { if (pseudo_header->portdest != - 0x80 /* Dsp OAM */ ) { + 0x80 /* Dsp OAM */) { state = STATE_DONE_PROV; break; } pseudo_header_len = ntohs(pseudo_header->length); /* Byte length for PROV records */ - // Get buffer for provisioning data + /* Get buffer for provisioning data */ pbuffer = kmalloc((pseudo_header_len + sizeof(struct pseudo_hdr)), @@ -1201,9 +1080,8 @@ u16 scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart, break; } /* End Switch */ - if (status != STATUS_SUCCESS) { + if (status != STATUS_SUCCESS) break; - } /**** // Check if Card is present diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index bc0d510fb0af..c57a6ba5d010 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -110,7 +110,7 @@ static int gdm_lte_rx(struct sk_buff *skb, struct nic *nic, int nic_type) return 0; } -int gdm_lte_emulate_arp(struct sk_buff *skb_in, u32 nic_type) +static int gdm_lte_emulate_arp(struct sk_buff *skb_in, u32 nic_type) { struct nic *nic = netdev_priv(skb_in->dev); struct sk_buff *skb_out; @@ -186,7 +186,7 @@ int gdm_lte_emulate_arp(struct sk_buff *skb_in, u32 nic_type) return 0; } -int icmp6_checksum(struct ipv6hdr *ipv6, u16 *ptr, int len) +static int icmp6_checksum(struct ipv6hdr *ipv6, u16 *ptr, int len) { unsigned short *w = ptr; int sum = 0; @@ -226,7 +226,7 @@ int icmp6_checksum(struct ipv6hdr *ipv6, u16 *ptr, int len) return sum; } -int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type) +static int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type) { struct nic *nic = netdev_priv(skb_in->dev); struct sk_buff *skb_out; diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c index 5b1ef4000d0f..62163673976c 100644 --- a/drivers/staging/gdm724x/gdm_mux.c +++ b/drivers/staging/gdm724x/gdm_mux.c @@ -26,7 +26,7 @@ #include "gdm_mux.h" -struct workqueue_struct *mux_rx_wq; +static struct workqueue_struct *mux_rx_wq; static u16 packet_type[TTY_MAX_COUNT] = {0xF011, 0xF010}; @@ -51,7 +51,7 @@ static const struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); -int packet_type_to_index(u16 packetType) +static int packet_type_to_index(u16 packetType) { int i; @@ -96,12 +96,12 @@ static struct mux_rx *alloc_mux_rx(void) { struct mux_rx *r = NULL; - r = kzalloc(sizeof(struct mux_rx), GFP_ATOMIC); + r = kzalloc(sizeof(struct mux_rx), GFP_KERNEL); if (!r) return NULL; - r->urb = usb_alloc_urb(0, GFP_ATOMIC); - r->buf = kmalloc(MUX_RX_MAX_SIZE, GFP_ATOMIC); + r->urb = usb_alloc_urb(0, GFP_KERNEL); + r->buf = kmalloc(MUX_RX_MAX_SIZE, GFP_KERNEL); if (!r->urb || !r->buf) { usb_free_urb(r->urb); kfree(r->buf); @@ -541,7 +541,7 @@ static int gdm_mux_probe(struct usb_interface *intf, const struct usb_device_id ret = init_usb(mux_dev); if (ret) - goto err_free_tty; + goto err_free_usb; tty_dev->priv_dev = (void *)mux_dev; tty_dev->send_func = gdm_mux_send; @@ -565,8 +565,8 @@ static int gdm_mux_probe(struct usb_interface *intf, const struct usb_device_id err_unregister_tty: unregister_lte_tty_device(tty_dev); +err_free_usb: release_usb(mux_dev); -err_free_tty: kfree(tty_dev); err_free_mux: kfree(mux_dev); diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c index 0247a2055e8d..c0f7cd75116b 100644 --- a/drivers/staging/gdm724x/gdm_tty.c +++ b/drivers/staging/gdm724x/gdm_tty.c @@ -171,7 +171,8 @@ static void gdm_tty_send_complete(void *arg) tty_port_tty_wakeup(&gdm->port); } -static int gdm_tty_write(struct tty_struct *tty, const unsigned char *buf, int len) +static int gdm_tty_write(struct tty_struct *tty, const unsigned char *buf, + int len) { struct gdm *gdm = tty->driver_data; int remain = len; @@ -185,7 +186,8 @@ static int gdm_tty_write(struct tty_struct *tty, const unsigned char *buf, int l return 0; while (1) { - sending_len = remain > MUX_TX_MAX_SIZE ? MUX_TX_MAX_SIZE : remain; + sending_len = remain > MUX_TX_MAX_SIZE ? MUX_TX_MAX_SIZE : + remain; gdm_tty_send(gdm, (void *)(buf+sent_len), sending_len, @@ -247,7 +249,8 @@ int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device) gdm->minor = j; gdm->tty_dev = tty_dev; - tty_port_register_device(&gdm->port, gdm_driver[i], gdm->minor, device); + tty_port_register_device(&gdm->port, gdm_driver[i], + gdm->minor, device); } for (i = 0; i < MAX_ISSUE_NUM; i++) @@ -309,7 +312,8 @@ int register_lte_tty_driver(void) tty_driver->major = GDM_TTY_MAJOR; tty_driver->type = TTY_DRIVER_TYPE_SERIAL; tty_driver->subtype = SERIAL_TYPE_NORMAL; - tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + tty_driver->flags = TTY_DRIVER_REAL_RAW | + TTY_DRIVER_DYNAMIC_DEV; tty_driver->init_termios = tty_std_termios; tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL; tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN; diff --git a/drivers/staging/iio/accel/sca3000_ring.c b/drivers/staging/iio/accel/sca3000_ring.c index 4a27beb1451a..ea0af6d81d2b 100644 --- a/drivers/staging/iio/accel/sca3000_ring.c +++ b/drivers/staging/iio/accel/sca3000_ring.c @@ -252,7 +252,7 @@ static struct iio_buffer *sca3000_rb_allocate(struct iio_dev *indio_dev) struct iio_buffer *buf; struct iio_hw_buffer *ring; - ring = kzalloc(sizeof *ring, GFP_KERNEL); + ring = kzalloc(sizeof(*ring), GFP_KERNEL); if (!ring) return NULL; diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index 14a28c4b3a46..7e7f9890a642 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -305,7 +305,7 @@ static int ad7150_read_event_value(struct iio_dev *indio_dev, return IIO_VAL_INT; default: return -EINVAL; - }; + } } static int ad7150_write_event_value(struct iio_dev *indio_dev, diff --git a/drivers/staging/imx-drm/Makefile b/drivers/staging/imx-drm/Makefile index bfaf69378ac2..2c3a9e178fb5 100644 --- a/drivers/staging/imx-drm/Makefile +++ b/drivers/staging/imx-drm/Makefile @@ -8,4 +8,4 @@ obj-$(CONFIG_DRM_IMX_TVE) += imx-tve.o obj-$(CONFIG_DRM_IMX_LDB) += imx-ldb.o obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o obj-$(CONFIG_DRM_IMX_IPUV3_CORE) += ipu-v3/ -obj-$(CONFIG_DRM_IMX_IPUV3) += ipuv3-crtc.o +obj-$(CONFIG_DRM_IMX_IPUV3) += ipuv3-crtc.o ipuv3-plane.o diff --git a/drivers/staging/imx-drm/TODO b/drivers/staging/imx-drm/TODO index 9cfa2a7efdc0..6a9da94c9573 100644 --- a/drivers/staging/imx-drm/TODO +++ b/drivers/staging/imx-drm/TODO @@ -9,7 +9,6 @@ TODO: Missing features (not necessarily for moving out of staging): -- Add KMS plane support for CRTC driver - Add i.MX6 HDMI support - Add support for IC (Image converter) - Add support for CSI (CMOS Sensor interface) diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index a2e52a0c53c9..d2fb699c0d1d 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c @@ -68,6 +68,11 @@ struct imx_drm_connector { struct module *owner; }; +int imx_drm_crtc_id(struct imx_drm_crtc *crtc) +{ + return crtc->pipe; +} + static void imx_drm_driver_lastclose(struct drm_device *drm) { struct imx_drm_device *imxdrm = drm->dev_private; @@ -110,18 +115,12 @@ int imx_drm_crtc_panel_format_pins(struct drm_crtc *crtc, u32 encoder_type, struct imx_drm_crtc *imx_crtc; struct imx_drm_crtc_helper_funcs *helper; - mutex_lock(&imxdrm->mutex); - list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list) if (imx_crtc->crtc == crtc) goto found; - mutex_unlock(&imxdrm->mutex); - return -EINVAL; found: - mutex_unlock(&imxdrm->mutex); - helper = &imx_crtc->imx_drm_helper_funcs; if (helper->set_interface_pix_fmt) return helper->set_interface_pix_fmt(crtc, @@ -191,6 +190,18 @@ static void imx_drm_disable_vblank(struct drm_device *drm, int crtc) imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc); } +static void imx_drm_driver_preclose(struct drm_device *drm, + struct drm_file *file) +{ + int i; + + if (!file->is_master) + return; + + for (i = 0; i < 4; i++) + imx_drm_disable_vblank(drm , i); +} + static const struct file_operations imx_drm_driver_fops = { .owner = THIS_MODULE, .open = drm_open, @@ -647,20 +658,14 @@ int imx_drm_encoder_get_mux_id(struct imx_drm_encoder *imx_drm_encoder, struct imx_drm_crtc *imx_crtc; int i = 0; - mutex_lock(&imxdrm->mutex); - list_for_each_entry(imx_crtc, &imxdrm->crtc_list, list) { if (imx_crtc->crtc == crtc) goto found; i++; } - mutex_unlock(&imxdrm->mutex); - return -EINVAL; found: - mutex_unlock(&imxdrm->mutex); - return i; } EXPORT_SYMBOL_GPL(imx_drm_encoder_get_mux_id); @@ -774,16 +779,26 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = { }; static struct drm_driver imx_drm_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, .load = imx_drm_driver_load, .unload = imx_drm_driver_unload, .lastclose = imx_drm_driver_lastclose, + .preclose = imx_drm_driver_preclose, .gem_free_object = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, .dumb_create = drm_gem_cma_dumb_create, .dumb_map_offset = drm_gem_cma_dumb_map_offset, .dumb_destroy = drm_gem_dumb_destroy, + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, + .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, + .gem_prime_vmap = drm_gem_cma_prime_vmap, + .gem_prime_vunmap = drm_gem_cma_prime_vunmap, + .gem_prime_mmap = drm_gem_cma_prime_mmap, .get_vblank_counter = drm_vblank_count, .enable_vblank = imx_drm_enable_vblank, .disable_vblank = imx_drm_disable_vblank, diff --git a/drivers/staging/imx-drm/imx-drm.h b/drivers/staging/imx-drm/imx-drm.h index f2aac91ddf5d..ae90c9c15312 100644 --- a/drivers/staging/imx-drm/imx-drm.h +++ b/drivers/staging/imx-drm/imx-drm.h @@ -14,6 +14,8 @@ struct drm_fbdev_cma; struct drm_framebuffer; struct platform_device; +int imx_drm_crtc_id(struct imx_drm_crtc *crtc); + struct imx_drm_crtc_helper_funcs { int (*enable_vblank)(struct drm_crtc *crtc); void (*disable_vblank)(struct drm_crtc *crtc); diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c index 33d6525cf996..59dd4d560ce0 100644 --- a/drivers/staging/imx-drm/imx-tve.c +++ b/drivers/staging/imx-drm/imx-tve.c @@ -696,7 +696,7 @@ static int imx_tve_probe(struct platform_device *pdev) if (val != 0x00100000) { dev_err(&pdev->dev, "configuration register default value indicates this is not a TVEv2\n"); return -ENODEV; - }; + } /* disable cable detection for VGA mode */ ret = regmap_write(tve->regmap, TVE_CD_CONT_REG, 0); diff --git a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h index 74c022e2a532..4826b5c0249d 100644 --- a/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h +++ b/drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h @@ -97,6 +97,7 @@ void ipu_idmac_put(struct ipuv3_channel *); int ipu_idmac_enable_channel(struct ipuv3_channel *channel); int ipu_idmac_disable_channel(struct ipuv3_channel *channel); +int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms); void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel, bool doublebuffer); @@ -283,7 +284,7 @@ int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p, int width); int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *, - struct ipu_rgb *rgb); + const struct ipu_rgb *rgb); static inline void ipu_cpmem_interlaced_scan(struct ipu_ch_param *p, int stride) @@ -303,6 +304,7 @@ int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat); int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem, struct ipu_image *image); +enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc); enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat); static inline void ipu_cpmem_set_burstsize(struct ipu_ch_param __iomem *p, diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c index ba464e5d9f12..a0e7fc2f4031 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c @@ -30,6 +30,8 @@ #include <linux/irqdomain.h> #include <linux/of_device.h> +#include <drm/drm_fourcc.h> + #include "imx-ipu-v3.h" #include "ipu-prv.h" @@ -139,7 +141,7 @@ u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs) EXPORT_SYMBOL_GPL(ipu_ch_param_read_field); int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *p, - struct ipu_rgb *rgb) + const struct ipu_rgb *rgb) { int bpp = 0, npb = 0, ro, go, bo, to; @@ -282,7 +284,7 @@ void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format, } EXPORT_SYMBOL_GPL(ipu_cpmem_set_yuv_planar); -static struct ipu_rgb def_rgb_32 = { +static const struct ipu_rgb def_rgb_32 = { .red = { .offset = 16, .length = 8, }, .green = { .offset = 8, .length = 8, }, .blue = { .offset = 0, .length = 8, }, @@ -290,31 +292,31 @@ static struct ipu_rgb def_rgb_32 = { .bits_per_pixel = 32, }; -static struct ipu_rgb def_bgr_32 = { - .red = { .offset = 16, .length = 8, }, +static const struct ipu_rgb def_bgr_32 = { + .red = { .offset = 0, .length = 8, }, .green = { .offset = 8, .length = 8, }, - .blue = { .offset = 0, .length = 8, }, + .blue = { .offset = 16, .length = 8, }, .transp = { .offset = 24, .length = 8, }, .bits_per_pixel = 32, }; -static struct ipu_rgb def_rgb_24 = { - .red = { .offset = 0, .length = 8, }, +static const struct ipu_rgb def_rgb_24 = { + .red = { .offset = 16, .length = 8, }, .green = { .offset = 8, .length = 8, }, - .blue = { .offset = 16, .length = 8, }, + .blue = { .offset = 0, .length = 8, }, .transp = { .offset = 0, .length = 0, }, .bits_per_pixel = 24, }; -static struct ipu_rgb def_bgr_24 = { - .red = { .offset = 16, .length = 8, }, +static const struct ipu_rgb def_bgr_24 = { + .red = { .offset = 0, .length = 8, }, .green = { .offset = 8, .length = 8, }, - .blue = { .offset = 0, .length = 8, }, + .blue = { .offset = 16, .length = 8, }, .transp = { .offset = 0, .length = 0, }, .bits_per_pixel = 24, }; -static struct ipu_rgb def_rgb_16 = { +static const struct ipu_rgb def_rgb_16 = { .red = { .offset = 11, .length = 5, }, .green = { .offset = 5, .length = 6, }, .blue = { .offset = 0, .length = 5, }, @@ -322,6 +324,14 @@ static struct ipu_rgb def_rgb_16 = { .bits_per_pixel = 16, }; +static const struct ipu_rgb def_bgr_16 = { + .red = { .offset = 0, .length = 5, }, + .green = { .offset = 5, .length = 6, }, + .blue = { .offset = 11, .length = 5, }, + .transp = { .offset = 0, .length = 0, }, + .bits_per_pixel = 16, +}; + #define Y_OFFSET(pix, x, y) ((x) + pix->width * (y)) #define U_OFFSET(pix, x, y) ((pix->width * pix->height) + \ (pix->width * (y) / 4) + (x) / 2) @@ -329,17 +339,17 @@ static struct ipu_rgb def_rgb_16 = { (pix->width * pix->height / 4) + \ (pix->width * (y) / 4) + (x) / 2) -int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat) +int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 drm_fourcc) { - switch (pixelformat) { - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_YVU420: + switch (drm_fourcc) { + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YVU420: /* pix format */ ipu_ch_param_write_field(cpmem, IPU_FIELD_PFS, 2); /* burst size */ ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 63); break; - case V4L2_PIX_FMT_UYVY: + case DRM_FORMAT_UYVY: /* bits/pixel */ ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3); /* pix format */ @@ -347,7 +357,7 @@ int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat) /* burst size */ ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31); break; - case V4L2_PIX_FMT_YUYV: + case DRM_FORMAT_YUYV: /* bits/pixel */ ipu_ch_param_write_field(cpmem, IPU_FIELD_BPP, 3); /* pix format */ @@ -355,20 +365,25 @@ int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat) /* burst size */ ipu_ch_param_write_field(cpmem, IPU_FIELD_NPB, 31); break; - case V4L2_PIX_FMT_RGB32: - ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32); + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_XBGR8888: + ipu_cpmem_set_format_rgb(cpmem, &def_bgr_32); break; - case V4L2_PIX_FMT_RGB565: - ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16); + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: + ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32); break; - case V4L2_PIX_FMT_BGR32: - ipu_cpmem_set_format_rgb(cpmem, &def_bgr_32); + case DRM_FORMAT_BGR888: + ipu_cpmem_set_format_rgb(cpmem, &def_bgr_24); break; - case V4L2_PIX_FMT_RGB24: + case DRM_FORMAT_RGB888: ipu_cpmem_set_format_rgb(cpmem, &def_rgb_24); break; - case V4L2_PIX_FMT_BGR24: - ipu_cpmem_set_format_rgb(cpmem, &def_bgr_24); + case DRM_FORMAT_RGB565: + ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16); + break; + case DRM_FORMAT_BGR565: + ipu_cpmem_set_format_rgb(cpmem, &def_bgr_16); break; default: return -EINVAL; @@ -378,6 +393,79 @@ int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat) } EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt); +/* + * The V4L2 spec defines packed RGB formats in memory byte order, which from + * point of view of the IPU corresponds to little-endian words with the first + * component in the least significant bits. + * The DRM pixel formats and IPU internal representation are ordered the other + * way around, with the first named component ordered at the most significant + * bits. Further, V4L2 formats are not well defined: + * http://linuxtv.org/downloads/v4l-dvb-apis/packed-rgb.html + * We choose the interpretation which matches GStreamer behavior. + */ +static int v4l2_pix_fmt_to_drm_fourcc(u32 pixelformat) +{ + switch (pixelformat) { + case V4L2_PIX_FMT_RGB565: + /* + * Here we choose the 'corrected' interpretation of RGBP, a + * little-endian 16-bit word with the red component at the most + * significant bits: + * g[2:0]b[4:0] r[4:0]g[5:3] <=> [16:0] R:G:B + */ + return DRM_FORMAT_RGB565; + case V4L2_PIX_FMT_BGR24: + /* B G R <=> [24:0] R:G:B */ + return DRM_FORMAT_RGB888; + case V4L2_PIX_FMT_RGB24: + /* R G B <=> [24:0] B:G:R */ + return DRM_FORMAT_BGR888; + case V4L2_PIX_FMT_BGR32: + /* B G R A <=> [32:0] A:B:G:R */ + return DRM_FORMAT_XRGB8888; + case V4L2_PIX_FMT_RGB32: + /* R G B A <=> [32:0] A:B:G:R */ + return DRM_FORMAT_XBGR8888; + case V4L2_PIX_FMT_UYVY: + return DRM_FORMAT_UYVY; + case V4L2_PIX_FMT_YUYV: + return DRM_FORMAT_YUYV; + case V4L2_PIX_FMT_YUV420: + return DRM_FORMAT_YUV420; + case V4L2_PIX_FMT_YVU420: + return DRM_FORMAT_YVU420; + } + + return -EINVAL; +} + +enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc) +{ + switch (drm_fourcc) { + case DRM_FORMAT_RGB565: + case DRM_FORMAT_BGR565: + case DRM_FORMAT_RGB888: + case DRM_FORMAT_BGR888: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRX8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_BGRA8888: + return IPUV3_COLORSPACE_RGB; + case DRM_FORMAT_YUYV: + case DRM_FORMAT_UYVY: + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YVU420: + return IPUV3_COLORSPACE_YUV; + default: + return IPUV3_COLORSPACE_UNKNOWN; + } +} +EXPORT_SYMBOL_GPL(ipu_drm_fourcc_to_colorspace); + int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem, struct ipu_image *image) { @@ -392,7 +480,7 @@ int ipu_cpmem_set_image(struct ipu_ch_param __iomem *cpmem, image->rect.height); ipu_cpmem_set_stride(cpmem, pix->bytesperline); - ipu_cpmem_set_fmt(cpmem, pix->pixelformat); + ipu_cpmem_set_fmt(cpmem, v4l2_pix_fmt_to_drm_fourcc(pix->pixelformat)); switch (pix->pixelformat) { case V4L2_PIX_FMT_YUV420: @@ -610,24 +698,29 @@ int ipu_idmac_enable_channel(struct ipuv3_channel *channel) } EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel); -int ipu_idmac_disable_channel(struct ipuv3_channel *channel) +int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms) { struct ipu_soc *ipu = channel->ipu; - u32 val; - unsigned long flags; unsigned long timeout; - timeout = jiffies + msecs_to_jiffies(50); + timeout = jiffies + msecs_to_jiffies(ms); while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) & idma_mask(channel->num)) { - if (time_after(jiffies, timeout)) { - dev_warn(ipu->dev, "disabling busy idmac channel %d\n", - channel->num); - break; - } + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; cpu_relax(); } + return 0; +} +EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy); + +int ipu_idmac_disable_channel(struct ipuv3_channel *channel) +{ + struct ipu_soc *ipu = channel->ipu; + u32 val; + unsigned long flags; + spin_lock_irqsave(&ipu->lock, flags); /* Disable DMA channel(s) */ @@ -888,7 +981,7 @@ static const struct ipu_platform_reg client_reg[] = { .dc = 5, .dp = IPU_DP_FLOW_SYNC_BG, .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC, - .dma[1] = -EINVAL, + .dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC, }, .name = "imx-ipuv3-crtc", }, { diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c index 21bf1c806528..1a6e06d1ebaf 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-dc.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-dc.c @@ -91,6 +91,7 @@ enum ipu_dc_map { IPU_DC_MAP_RGB565, IPU_DC_MAP_GBR24, /* TVEv2 */ IPU_DC_MAP_BGR666, + IPU_DC_MAP_BGR24, }; struct ipu_dc { @@ -152,6 +153,8 @@ static int ipu_pixfmt_to_map(u32 fmt) return IPU_DC_MAP_GBR24; case V4L2_PIX_FMT_BGR666: return IPU_DC_MAP_BGR666; + case V4L2_PIX_FMT_BGR24: + return IPU_DC_MAP_BGR24; default: return -EINVAL; } @@ -395,6 +398,12 @@ int ipu_dc_init(struct ipu_soc *ipu, struct device *dev, ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */ ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */ + /* bgr24 */ + ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24); + ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */ + ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */ + ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */ + return 0; } diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c index 2e97c33b81e7..98070dd8c920 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-dmfc.c @@ -307,13 +307,13 @@ int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc, goto out; } - /* Always allocate at least 128*4 bytes (2 slots) */ - if (slots < 2) - slots = 2; - /* For the MEM_BG channel, first try to allocate twice the slots */ if (dmfc->data->ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC) segment = dmfc_find_slots(priv, slots * 2); + else if (slots < 2) + /* Always allocate at least 128*4 bytes (2 slots) */ + slots = 2; + if (segment >= 0) slots *= 2; else diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c index 6fd37a7453e9..f1112dfa6bf6 100644 --- a/drivers/staging/imx-drm/ipuv3-crtc.c +++ b/drivers/staging/imx-drm/ipuv3-crtc.c @@ -25,29 +25,25 @@ #include <drm/drm_crtc_helper.h> #include <linux/fb.h> #include <linux/clk.h> +#include <linux/errno.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_fb_cma_helper.h> #include "ipu-v3/imx-ipu-v3.h" #include "imx-drm.h" +#include "ipuv3-plane.h" #define DRIVER_DESC "i.MX IPUv3 Graphics" -struct ipu_framebuffer { - struct drm_framebuffer base; - void *virt; - dma_addr_t phys; - size_t len; -}; - struct ipu_crtc { struct device *dev; struct drm_crtc base; struct imx_drm_crtc *imx_crtc; - struct ipuv3_channel *ipu_ch; + + /* plane[0] is the full plane, plane[1] is the partial plane */ + struct ipu_plane *plane[2]; + struct ipu_dc *dc; - struct ipu_dp *dp; - struct dmfc_channel *dmfc; struct ipu_di *di; int enabled; struct drm_pending_vblank_event *page_flip_event; @@ -61,35 +57,14 @@ struct ipu_crtc { #define to_ipu_crtc(x) container_of(x, struct ipu_crtc, base) -static int calc_vref(struct drm_display_mode *mode) -{ - unsigned long htotal, vtotal; - - htotal = mode->htotal; - vtotal = mode->vtotal; - - if (!htotal || !vtotal) - return 60; - - return mode->clock * 1000 / vtotal / htotal; -} - -static int calc_bandwidth(struct drm_display_mode *mode, unsigned int vref) -{ - return mode->hdisplay * mode->vdisplay * vref; -} - static void ipu_fb_enable(struct ipu_crtc *ipu_crtc) { if (ipu_crtc->enabled) return; ipu_di_enable(ipu_crtc->di); - ipu_dmfc_enable_channel(ipu_crtc->dmfc); - ipu_idmac_enable_channel(ipu_crtc->ipu_ch); ipu_dc_enable_channel(ipu_crtc->dc); - if (ipu_crtc->dp) - ipu_dp_enable_channel(ipu_crtc->dp); + ipu_plane_enable(ipu_crtc->plane[0]); ipu_crtc->enabled = 1; } @@ -99,11 +74,8 @@ static void ipu_fb_disable(struct ipu_crtc *ipu_crtc) if (!ipu_crtc->enabled) return; - if (ipu_crtc->dp) - ipu_dp_disable_channel(ipu_crtc->dp); + ipu_plane_disable(ipu_crtc->plane[0]); ipu_dc_disable_channel(ipu_crtc->dc); - ipu_idmac_disable_channel(ipu_crtc->ipu_ch); - ipu_dmfc_disable_channel(ipu_crtc->dmfc); ipu_di_disable(ipu_crtc->di); ipu_crtc->enabled = 0; @@ -159,33 +131,6 @@ static const struct drm_crtc_funcs ipu_crtc_funcs = { .page_flip = ipu_page_flip, }; -static int ipu_drm_set_base(struct drm_crtc *crtc, int x, int y) -{ - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - struct drm_gem_cma_object *cma_obj; - struct drm_framebuffer *fb = crtc->fb; - unsigned long phys; - - cma_obj = drm_fb_cma_get_gem_obj(fb, 0); - if (!cma_obj) { - DRM_LOG_KMS("entry is null.\n"); - return -EFAULT; - } - - phys = cma_obj->paddr; - phys += x * (fb->bits_per_pixel >> 3); - phys += y * fb->pitches[0]; - - dev_dbg(ipu_crtc->dev, "%s: phys: 0x%lx\n", __func__, phys); - dev_dbg(ipu_crtc->dev, "%s: xy: %dx%d\n", __func__, x, y); - - ipu_cpmem_set_stride(ipu_get_cpmem(ipu_crtc->ipu_ch), fb->pitches[0]); - ipu_cpmem_set_buffer(ipu_get_cpmem(ipu_crtc->ipu_ch), - 0, phys); - - return 0; -} - static int ipu_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *orig_mode, struct drm_display_mode *mode, @@ -193,41 +138,15 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) { struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - struct drm_framebuffer *fb = ipu_crtc->base.fb; int ret; struct ipu_di_signal_cfg sig_cfg = {}; u32 out_pixel_fmt; - struct ipu_ch_param __iomem *cpmem = ipu_get_cpmem(ipu_crtc->ipu_ch); - int bpp; - u32 v4l2_fmt; dev_dbg(ipu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__, mode->hdisplay); dev_dbg(ipu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__, mode->vdisplay); - ipu_ch_param_zero(cpmem); - - switch (fb->pixel_format) { - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ARGB8888: - v4l2_fmt = V4L2_PIX_FMT_RGB32; - bpp = 32; - break; - case DRM_FORMAT_RGB565: - v4l2_fmt = V4L2_PIX_FMT_RGB565; - bpp = 16; - break; - case DRM_FORMAT_RGB888: - v4l2_fmt = V4L2_PIX_FMT_RGB24; - bpp = 24; - break; - default: - dev_err(ipu_crtc->dev, "unsupported pixel format 0x%08x\n", - fb->pixel_format); - return -EINVAL; - } - out_pixel_fmt = ipu_crtc->interface_pix_fmt; if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -257,18 +176,6 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc, sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin; sig_cfg.vsync_pin = ipu_crtc->di_vsync_pin; - if (ipu_crtc->dp) { - ret = ipu_dp_setup_channel(ipu_crtc->dp, IPUV3_COLORSPACE_RGB, - IPUV3_COLORSPACE_RGB); - if (ret) { - dev_err(ipu_crtc->dev, - "initializing display processor failed with %d\n", - ret); - return ret; - } - ipu_dp_set_global_alpha(ipu_crtc->dp, 1, 0, 1); - } - ret = ipu_dc_init_sync(ipu_crtc->dc, ipu_crtc->di, sig_cfg.interlaced, out_pixel_fmt, mode->hdisplay); if (ret) { @@ -285,30 +192,9 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc, return ret; } - ipu_cpmem_set_resolution(cpmem, mode->hdisplay, mode->vdisplay); - ipu_cpmem_set_fmt(cpmem, v4l2_fmt); - ipu_cpmem_set_high_priority(ipu_crtc->ipu_ch); - - ret = ipu_dmfc_init_channel(ipu_crtc->dmfc, mode->hdisplay); - if (ret) { - dev_err(ipu_crtc->dev, - "initializing dmfc channel failed with %d\n", - ret); - return ret; - } - - ret = ipu_dmfc_alloc_bandwidth(ipu_crtc->dmfc, - calc_bandwidth(mode, calc_vref(mode)), 64); - if (ret) { - dev_err(ipu_crtc->dev, - "allocating dmfc bandwidth failed with %d\n", - ret); - return ret; - } - - ipu_drm_set_base(crtc, x, y); - - return 0; + return ipu_plane_mode_set(ipu_crtc->plane[0], crtc, mode, crtc->fb, + 0, 0, mode->hdisplay, mode->vdisplay, + x, y, mode->hdisplay, mode->vdisplay); } static void ipu_crtc_handle_pageflip(struct ipu_crtc *ipu_crtc) @@ -332,7 +218,7 @@ static irqreturn_t ipu_irq_handler(int irq, void *dev_id) if (ipu_crtc->newfb) { ipu_crtc->newfb = NULL; - ipu_drm_set_base(&ipu_crtc->base, 0, 0); + ipu_plane_set_base(ipu_crtc->plane[0], ipu_crtc->base.fb, 0, 0); ipu_crtc_handle_pageflip(ipu_crtc); } @@ -370,10 +256,6 @@ static struct drm_crtc_helper_funcs ipu_helper_funcs = { static int ipu_enable_vblank(struct drm_crtc *crtc) { - struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - - enable_irq(ipu_crtc->irq); - return 0; } @@ -381,7 +263,8 @@ static void ipu_disable_vblank(struct drm_crtc *crtc) { struct ipu_crtc *ipu_crtc = to_ipu_crtc(crtc); - disable_irq(ipu_crtc->irq); + ipu_crtc->page_flip_event = NULL; + ipu_crtc->newfb = NULL; } static int ipu_set_interface_pix_fmt(struct drm_crtc *crtc, u32 encoder_type, @@ -418,12 +301,8 @@ static const struct imx_drm_crtc_helper_funcs ipu_crtc_helper_funcs = { static void ipu_put_resources(struct ipu_crtc *ipu_crtc) { - if (!IS_ERR_OR_NULL(ipu_crtc->ipu_ch)) - ipu_idmac_put(ipu_crtc->ipu_ch); - if (!IS_ERR_OR_NULL(ipu_crtc->dmfc)) - ipu_dmfc_put(ipu_crtc->dmfc); - if (!IS_ERR_OR_NULL(ipu_crtc->dp)) - ipu_dp_put(ipu_crtc->dp); + if (!IS_ERR_OR_NULL(ipu_crtc->dc)) + ipu_dc_put(ipu_crtc->dc); if (!IS_ERR_OR_NULL(ipu_crtc->di)) ipu_di_put(ipu_crtc->di); } @@ -434,32 +313,12 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc, struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); int ret; - ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]); - if (IS_ERR(ipu_crtc->ipu_ch)) { - ret = PTR_ERR(ipu_crtc->ipu_ch); - goto err_out; - } - ipu_crtc->dc = ipu_dc_get(ipu, pdata->dc); if (IS_ERR(ipu_crtc->dc)) { ret = PTR_ERR(ipu_crtc->dc); goto err_out; } - ipu_crtc->dmfc = ipu_dmfc_get(ipu, pdata->dma[0]); - if (IS_ERR(ipu_crtc->dmfc)) { - ret = PTR_ERR(ipu_crtc->dmfc); - goto err_out; - } - - if (pdata->dp >= 0) { - ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp); - if (IS_ERR(ipu_crtc->dp)) { - ret = PTR_ERR(ipu_crtc->dp); - goto err_out; - } - } - ipu_crtc->di = ipu_di_get(ipu, pdata->di); if (IS_ERR(ipu_crtc->di)) { ret = PTR_ERR(ipu_crtc->di); @@ -477,7 +336,9 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, struct ipu_client_platformdata *pdata) { struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); + int dp = -EINVAL; int ret; + int id; ret = ipu_get_resources(ipu_crtc, pdata); if (ret) { @@ -495,19 +356,42 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, goto err_put_resources; } - ipu_crtc->irq = ipu_idmac_channel_irq(ipu, ipu_crtc->ipu_ch, - IPU_IRQ_EOF); + if (pdata->dp >= 0) + dp = IPU_DP_FLOW_SYNC_BG; + id = imx_drm_crtc_id(ipu_crtc->imx_crtc); + ipu_crtc->plane[0] = ipu_plane_init(ipu_crtc->base.dev, ipu, + pdata->dma[0], dp, BIT(id), true); + ret = ipu_plane_get_resources(ipu_crtc->plane[0]); + if (ret) { + dev_err(ipu_crtc->dev, "getting plane 0 resources failed with %d.\n", + ret); + goto err_remove_crtc; + } + + /* If this crtc is using the DP, add an overlay plane */ + if (pdata->dp >= 0 && pdata->dma[1] > 0) { + ipu_crtc->plane[1] = ipu_plane_init(ipu_crtc->base.dev, ipu, + pdata->dma[1], + IPU_DP_FLOW_SYNC_FG, + BIT(id), false); + if (IS_ERR(ipu_crtc->plane[1])) + ipu_crtc->plane[1] = NULL; + } + + ipu_crtc->irq = ipu_plane_irq(ipu_crtc->plane[0]); ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0, "imx_drm", ipu_crtc); if (ret < 0) { dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret); - goto err_put_resources; + goto err_put_plane_res; } - disable_irq(ipu_crtc->irq); - return 0; +err_put_plane_res: + ipu_plane_put_resources(ipu_crtc->plane[0]); +err_remove_crtc: + imx_drm_remove_crtc(ipu_crtc->imx_crtc); err_put_resources: ipu_put_resources(ipu_crtc); @@ -546,6 +430,7 @@ static int ipu_drm_remove(struct platform_device *pdev) imx_drm_remove_crtc(ipu_crtc->imx_crtc); + ipu_plane_put_resources(ipu_crtc->plane[0]); ipu_put_resources(ipu_crtc); return 0; diff --git a/drivers/staging/imx-drm/ipuv3-plane.c b/drivers/staging/imx-drm/ipuv3-plane.c new file mode 100644 index 000000000000..d97454a0dffd --- /dev/null +++ b/drivers/staging/imx-drm/ipuv3-plane.c @@ -0,0 +1,375 @@ +/* + * i.MX IPUv3 DP Overlay Planes + * + * Copyright (C) 2013 Philipp Zabel, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the 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 <drm/drmP.h> +#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_gem_cma_helper.h> + +#include "ipu-v3/imx-ipu-v3.h" +#include "ipuv3-plane.h" + +#define to_ipu_plane(x) container_of(x, struct ipu_plane, base) + +static const uint32_t ipu_plane_formats[] = { + DRM_FORMAT_XRGB1555, + DRM_FORMAT_XBGR1555, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, + DRM_FORMAT_YUV420, + DRM_FORMAT_YVU420, +}; + +int ipu_plane_irq(struct ipu_plane *ipu_plane) +{ + return ipu_idmac_channel_irq(ipu_plane->ipu, ipu_plane->ipu_ch, + IPU_IRQ_EOF); +} + +static int calc_vref(struct drm_display_mode *mode) +{ + unsigned long htotal, vtotal; + + htotal = mode->htotal; + vtotal = mode->vtotal; + + if (!htotal || !vtotal) + return 60; + + return DIV_ROUND_UP(mode->clock * 1000, vtotal * htotal); +} + +static inline int calc_bandwidth(int width, int height, unsigned int vref) +{ + return width * height * vref; +} + +int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct drm_framebuffer *fb, + int x, int y) +{ + struct ipu_ch_param __iomem *cpmem; + struct drm_gem_cma_object *cma_obj; + + cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + if (!cma_obj) { + DRM_LOG_KMS("entry is null.\n"); + return -EFAULT; + } + + dev_dbg(ipu_plane->base.dev->dev, "phys = 0x%x, x = %d, y = %d", + cma_obj->paddr, x, y); + + cpmem = ipu_get_cpmem(ipu_plane->ipu_ch); + ipu_cpmem_set_stride(cpmem, fb->pitches[0]); + ipu_cpmem_set_buffer(cpmem, 0, cma_obj->paddr + fb->offsets[0] + + fb->pitches[0] * y + x); + + return 0; +} + +int ipu_plane_mode_set(struct ipu_plane *ipu_plane, struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_framebuffer *fb, int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h) +{ + struct ipu_ch_param __iomem *cpmem; + struct device *dev = ipu_plane->base.dev->dev; + int ret; + + /* no scaling */ + if (src_w != crtc_w || src_h != crtc_h) + return -EINVAL; + + /* clip to crtc bounds */ + if (crtc_x < 0) { + if (-crtc_x > crtc_w) + return -EINVAL; + src_x += -crtc_x; + src_w -= -crtc_x; + crtc_w -= -crtc_x; + crtc_x = 0; + } + if (crtc_y < 0) { + if (-crtc_y > crtc_h) + return -EINVAL; + src_y += -crtc_y; + src_h -= -crtc_y; + crtc_h -= -crtc_y; + crtc_y = 0; + } + if (crtc_x + crtc_w > mode->hdisplay) { + if (crtc_x > mode->hdisplay) + return -EINVAL; + crtc_w = mode->hdisplay - crtc_x; + src_w = crtc_w; + } + if (crtc_y + crtc_h > mode->vdisplay) { + if (crtc_y > mode->vdisplay) + return -EINVAL; + crtc_h = mode->vdisplay - crtc_y; + src_h = crtc_h; + } + /* full plane minimum width is 13 pixels */ + if (crtc_w < 13 && (ipu_plane->dp_flow != IPU_DP_FLOW_SYNC_FG)) + return -EINVAL; + if (crtc_h < 2) + return -EINVAL; + + switch (ipu_plane->dp_flow) { + case IPU_DP_FLOW_SYNC_BG: + ret = ipu_dp_setup_channel(ipu_plane->dp, + IPUV3_COLORSPACE_RGB, + IPUV3_COLORSPACE_RGB); + if (ret) { + dev_err(dev, + "initializing display processor failed with %d\n", + ret); + return ret; + } + ipu_dp_set_global_alpha(ipu_plane->dp, 1, 0, 1); + break; + case IPU_DP_FLOW_SYNC_FG: + ipu_dp_setup_channel(ipu_plane->dp, + ipu_drm_fourcc_to_colorspace(fb->pixel_format), + IPUV3_COLORSPACE_UNKNOWN); + ipu_dp_set_window_pos(ipu_plane->dp, crtc_x, crtc_y); + break; + } + + ret = ipu_dmfc_init_channel(ipu_plane->dmfc, crtc_w); + if (ret) { + dev_err(dev, "initializing dmfc channel failed with %d\n", ret); + return ret; + } + + ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc, + calc_bandwidth(crtc_w, crtc_h, + calc_vref(mode)), 64); + if (ret) { + dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret); + return ret; + } + + cpmem = ipu_get_cpmem(ipu_plane->ipu_ch); + ipu_ch_param_zero(cpmem); + ipu_cpmem_set_resolution(cpmem, src_w, src_h); + ret = ipu_cpmem_set_fmt(cpmem, fb->pixel_format); + if (ret < 0) { + dev_err(dev, "unsupported pixel format 0x%08x\n", + fb->pixel_format); + return ret; + } + ipu_cpmem_set_high_priority(ipu_plane->ipu_ch); + + ret = ipu_plane_set_base(ipu_plane, fb, src_x, src_y); + if (ret < 0) + return ret; + + return 0; +} + +void ipu_plane_put_resources(struct ipu_plane *ipu_plane) +{ + if (!IS_ERR_OR_NULL(ipu_plane->dp)) + ipu_dp_put(ipu_plane->dp); + if (!IS_ERR_OR_NULL(ipu_plane->dmfc)) + ipu_dmfc_put(ipu_plane->dmfc); + if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch)) + ipu_idmac_put(ipu_plane->ipu_ch); +} + +int ipu_plane_get_resources(struct ipu_plane *ipu_plane) +{ + int ret; + + ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma); + if (IS_ERR(ipu_plane->ipu_ch)) { + ret = PTR_ERR(ipu_plane->ipu_ch); + DRM_ERROR("failed to get idmac channel: %d\n", ret); + return ret; + } + + ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma); + if (IS_ERR(ipu_plane->dmfc)) { + ret = PTR_ERR(ipu_plane->dmfc); + DRM_ERROR("failed to get dmfc: ret %d\n", ret); + goto err_out; + } + + if (ipu_plane->dp_flow >= 0) { + ipu_plane->dp = ipu_dp_get(ipu_plane->ipu, ipu_plane->dp_flow); + if (IS_ERR(ipu_plane->dp)) { + ret = PTR_ERR(ipu_plane->dp); + DRM_ERROR("failed to get dp flow: %d\n", ret); + goto err_out; + } + } + + return 0; +err_out: + ipu_plane_put_resources(ipu_plane); + + return ret; +} + +void ipu_plane_enable(struct ipu_plane *ipu_plane) +{ + ipu_dmfc_enable_channel(ipu_plane->dmfc); + ipu_idmac_enable_channel(ipu_plane->ipu_ch); + if (ipu_plane->dp) + ipu_dp_enable_channel(ipu_plane->dp); + + ipu_plane->enabled = true; +} + +void ipu_plane_disable(struct ipu_plane *ipu_plane) +{ + ipu_plane->enabled = false; + + ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50); + + if (ipu_plane->dp) + ipu_dp_disable_channel(ipu_plane->dp); + ipu_idmac_disable_channel(ipu_plane->ipu_ch); + ipu_dmfc_disable_channel(ipu_plane->dmfc); +} + +static void ipu_plane_dpms(struct ipu_plane *ipu_plane, int mode) +{ + bool enable; + + DRM_DEBUG_KMS("mode = %d", mode); + + enable = (mode == DRM_MODE_DPMS_ON); + + if (enable == ipu_plane->enabled) + return; + + if (enable) { + ipu_plane_enable(ipu_plane); + } else { + ipu_plane_disable(ipu_plane); + + ipu_idmac_put(ipu_plane->ipu_ch); + ipu_dmfc_put(ipu_plane->dmfc); + ipu_dp_put(ipu_plane->dp); + } +} + +/* + * drm_plane API + */ + +static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc, + struct drm_framebuffer *fb, int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, + uint32_t src_w, uint32_t src_h) +{ + struct ipu_plane *ipu_plane = to_ipu_plane(plane); + int ret = 0; + + DRM_DEBUG_KMS("plane - %p\n", plane); + + if (!ipu_plane->enabled) + ret = ipu_plane_get_resources(ipu_plane); + if (ret < 0) + return ret; + + ret = ipu_plane_mode_set(ipu_plane, crtc, &crtc->hwmode, fb, + crtc_x, crtc_y, crtc_w, crtc_h, + src_x >> 16, src_y >> 16, src_w >> 16, src_h >> 16); + if (ret < 0) { + ipu_plane_put_resources(ipu_plane); + return ret; + } + + if (crtc != plane->crtc) + dev_info(plane->dev->dev, "crtc change: %p -> %p\n", + plane->crtc, crtc); + plane->crtc = crtc; + + ipu_plane_dpms(ipu_plane, DRM_MODE_DPMS_ON); + + return 0; +} + +static int ipu_disable_plane(struct drm_plane *plane) +{ + struct ipu_plane *ipu_plane = to_ipu_plane(plane); + + DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); + + ipu_plane_dpms(ipu_plane, DRM_MODE_DPMS_OFF); + + ipu_plane_put_resources(ipu_plane); + + return 0; +} + +static void ipu_plane_destroy(struct drm_plane *plane) +{ + struct ipu_plane *ipu_plane = to_ipu_plane(plane); + + DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); + + ipu_disable_plane(plane); + drm_plane_cleanup(plane); + kfree(ipu_plane); +} + +static struct drm_plane_funcs ipu_plane_funcs = { + .update_plane = ipu_update_plane, + .disable_plane = ipu_disable_plane, + .destroy = ipu_plane_destroy, +}; + +struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, + int dma, int dp, unsigned int possible_crtcs, + bool priv) +{ + struct ipu_plane *ipu_plane; + int ret; + + DRM_DEBUG_KMS("channel %d, dp flow %d, possible_crtcs=0x%x\n", + dma, dp, possible_crtcs); + + ipu_plane = kzalloc(sizeof(*ipu_plane), GFP_KERNEL); + if (!ipu_plane) { + DRM_ERROR("failed to allocate plane\n"); + return ERR_PTR(-ENOMEM); + } + + ipu_plane->ipu = ipu; + ipu_plane->dma = dma; + ipu_plane->dp_flow = dp; + + ret = drm_plane_init(dev, &ipu_plane->base, possible_crtcs, + &ipu_plane_funcs, ipu_plane_formats, + ARRAY_SIZE(ipu_plane_formats), + priv); + if (ret) { + DRM_ERROR("failed to initialize plane\n"); + kfree(ipu_plane); + return ERR_PTR(ret); + } + + return ipu_plane; +} diff --git a/drivers/staging/imx-drm/ipuv3-plane.h b/drivers/staging/imx-drm/ipuv3-plane.h new file mode 100644 index 000000000000..c0aae5bcb5d4 --- /dev/null +++ b/drivers/staging/imx-drm/ipuv3-plane.h @@ -0,0 +1,55 @@ +#ifndef __IPUV3_PLANE_H__ +#define __IPUV3_PLANE_H__ + +#include <drm/drm_crtc.h> /* drm_plane */ + +struct drm_plane; +struct drm_device; +struct ipu_soc; +struct drm_crtc; +struct drm_framebuffer; + +struct ipuv3_channel; +struct dmfc_channel; +struct ipu_dp; + +struct ipu_plane { + struct drm_plane base; + + struct ipu_soc *ipu; + struct ipuv3_channel *ipu_ch; + struct dmfc_channel *dmfc; + struct ipu_dp *dp; + + int dma; + int dp_flow; + + int x; + int y; + + bool enabled; +}; + +struct ipu_plane *ipu_plane_init(struct drm_device *dev, struct ipu_soc *ipu, + int dma, int dp, unsigned int possible_crtcs, + bool priv); + +/* Init IDMAC, DMFC, DP */ +int ipu_plane_mode_set(struct ipu_plane *plane, struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_framebuffer *fb, int crtc_x, int crtc_y, + unsigned int crtc_w, unsigned int crtc_h, + uint32_t src_x, uint32_t src_y, uint32_t src_w, + uint32_t src_h); + +void ipu_plane_enable(struct ipu_plane *plane); +void ipu_plane_disable(struct ipu_plane *plane); +int ipu_plane_set_base(struct ipu_plane *plane, struct drm_framebuffer *fb, + int x, int y); + +int ipu_plane_get_resources(struct ipu_plane *plane); +void ipu_plane_put_resources(struct ipu_plane *plane); + +int ipu_plane_irq(struct ipu_plane *plane); + +#endif diff --git a/drivers/staging/ktap/Kconfig b/drivers/staging/ktap/Kconfig new file mode 100644 index 000000000000..21f8d2ed03b9 --- /dev/null +++ b/drivers/staging/ktap/Kconfig @@ -0,0 +1,21 @@ +config KTAP + tristate "a programable dynamic tracing tool for Linux" + depends on PERF_EVENTS && EVENT_TRACING + default n + help + ktap is a new script-based dynamic tracing tool for Linux, + it uses a scripting language and lets users trace the + Linux kernel dynamically. ktap is designed to give + operational insights with interoperability that allow + users to tune, troubleshoot and extend kernel and application. + It's similar with Linux Systemtap and Solaris Dtrace. + + ktap have different design principles from Linux mainstream + dynamic tracing language in that it's based on bytecode, + so it doesn't depend upon GCC, doesn't require compiling + kernel module for each script, safe to use in production + environment, fulfilling the embedded ecosystem's tracing needs. + + See ktap tutorial for more information: + http://www.ktap.org/doc/tutorial.html + diff --git a/drivers/staging/ktap/Makefile b/drivers/staging/ktap/Makefile new file mode 100644 index 000000000000..e2e54baf36d9 --- /dev/null +++ b/drivers/staging/ktap/Makefile @@ -0,0 +1,101 @@ + +# Do not instrument the tracer itself: +ifdef CONFIG_FUNCTION_TRACER +ORIG_CFLAGS := $(KBUILD_CFLAGS) +KBUILD_CFLAGS = $(subst -pg,,$(ORIG_CFLAGS)) +endif + +all: mod ktap + +INTP = interpreter + +LIBDIR = $(INTP)/library + +LIB_OBJS += $(LIBDIR)/baselib.o $(LIBDIR)/kdebug.o $(LIBDIR)/timer.o \ + $(LIBDIR)/ansilib.o + +INTP_OBJS += $(INTP)/ktap.o $(INTP)/loader.o $(INTP)/object.o \ + $(INTP)/tstring.o $(INTP)/table.o $(INTP)/vm.o \ + $(INTP)/opcode.o $(INTP)/strfmt.o $(INTP)/transport.o \ + $(LIB_OBJS) + +obj-m += ktapvm.o +ktapvm-y := $(INTP_OBJS) + +KVERSION ?= $(shell uname -r) +KERNEL_SRC ?= /lib/modules/$(KVERSION)/build +mod: + $(MAKE) -C $(KERNEL_SRC) M=$(PWD) modules + +modules_install: + $(MAKE) -C $(KERNEL_SRC) M=$(PWD) modules_install + +KTAPC_CFLAGS = -Wall -O2 + +UDIR = userspace + +$(UDIR)/lex.o: $(UDIR)/lex.c + $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $< +$(UDIR)/parser.o: $(UDIR)/parser.c + $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $< +$(UDIR)/code.o: $(UDIR)/code.c + $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $< +$(UDIR)/dump.o: $(UDIR)/dump.c + $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $< +$(UDIR)/main.o: $(UDIR)/main.c + $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $< +$(UDIR)/util.o: $(UDIR)/util.c + $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $< +$(UDIR)/ktapio.o: $(UDIR)/ktapio.c + $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $< +$(UDIR)/eventdef.o: $(UDIR)/eventdef.c + $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $< +$(UDIR)/opcode.o: $(INTP)/opcode.c + $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $< +$(UDIR)/table.o: $(INTP)/table.c + $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $< +$(UDIR)/tstring.o: $(INTP)/tstring.c + $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $< +$(UDIR)/object.o: $(INTP)/object.c + $(QUIET_CC)$(CC) $(DEBUGINFO_FLAG) $(KTAPC_CFLAGS) -o $@ -c $< + +KTAPOBJS = +KTAPOBJS += $(UDIR)/lex.o +KTAPOBJS += $(UDIR)/parser.o +KTAPOBJS += $(UDIR)/code.o +KTAPOBJS += $(UDIR)/dump.o +KTAPOBJS += $(UDIR)/main.o +KTAPOBJS += $(UDIR)/util.o +KTAPOBJS += $(UDIR)/ktapio.o +KTAPOBJS += $(UDIR)/eventdef.o +KTAPOBJS += $(UDIR)/opcode.o +KTAPOBJS += $(UDIR)/table.o +KTAPOBJS += $(UDIR)/tstring.o +KTAPOBJS += $(UDIR)/object.o + +ktap: $(KTAPOBJS) + $(QUIET_LINK)$(CC) $(KTAPC_CFLAGS) -o $@ $(KTAPOBJS) -lpthread + +KMISC := /lib/modules/$(KVERSION)/ktapvm/ + +install: mod ktap + install -d $(KMISC) + install -m 644 -c *.ko /lib/modules/$(KVERSION)/ktapvm/ + /sbin/depmod -a + +load: + insmod ktapvm.ko + +unload: + rmmod ktapvm + +test: FORCE + cd test; sh ./run_test.sh; cd - + +clean: + $(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean + $(RM) ktap + +PHONY += FORCE +FORCE: + diff --git a/drivers/staging/ktap/README.md b/drivers/staging/ktap/README.md new file mode 100644 index 000000000000..c8ddd5fa66c6 --- /dev/null +++ b/drivers/staging/ktap/README.md @@ -0,0 +1,144 @@ +# ktap + +A New Scripting Dynamic Tracing Tool For Linux +[www.ktap.org][homepage] + +ktap is a new scripting dynamic tracing tool for Linux, +it uses a scripting language and lets users trace the Linux kernel dynamically. +ktap is designed to give operational insights with interoperability +that allows users to tune, troubleshoot and extend kernel and application. +It's similar with Linux Systemtap and Solaris Dtrace. + +ktap have different design principles from Linux mainstream dynamic tracing +language in that it's based on bytecode, so it doesn't depend upon GCC, +doesn't require compiling kernel module for each script, safe to use in +production environment, fulfilling the embedded ecosystem's tracing needs. + +More information can be found at [ktap homepage][homepage]. + +[homepage]: http://www.ktap.org + +## Highlights + + * simple but powerful scripting language + * register based interpreter (heavily optimized) in Linux kernel + * small and lightweight (6KLOC of interpreter) + * not depend on gcc for each script running + * easy to use in embedded environment without debugging info + * support for tracepoint, kprobe, uprobe, function trace, timer, and more + * supported in x86, arm, ppc, mips + * safety in sandbox + +## Building & Running + +1. Clone ktap from github + + $ git clone http://github.com/ktap/ktap.git + +2. Compiling ktap + + $ cd ktap + $ make #generate ktapvm kernel module and ktap binary + +3. Load ktapvm kernel module(make sure debugfs mounted) + + $ make load #need to be root or have sudo access + +4. Running ktap + + $ ./ktap scripts/helloworld.kp + + +## Examples + +1. simplest one-liner command to enable all tracepoints + + ktap -e "trace *:* { print(argevent) }" + +2. syscall tracing on target process + + ktap -e "trace syscalls:* { print(argevent) }" -- ls + +3. function tracing + + ktap -e "trace ftrace:function { print(argevent) }" + + ktap -e "trace ftrace:function /ip==mutex*/ { print(argevent) }" + +4. simple syscall tracing + + trace syscalls:* { + print(cpu(), pid(), execname(), argevent) + } + +5. syscall tracing in histogram style + + s = {} + + trace syscalls:sys_enter_* { + s[argname] += 1 + } + + trace_end { + histogram(s) + } + +6. kprobe tracing + + trace probe:do_sys_open dfd=%di fname=%dx flags=%cx mode=+4($stack) { + print("entry:", execname(), argevent) + } + + trace probe:do_sys_open%return fd=$retval { + print("exit:", execname(), argevent) + } + +7. uprobe tracing + + trace probe:/lib/libc.so.6:0x000773c0 { + print("entry:", execname(), argevent) + } + + trace probe:/lib/libc.so.6:0x000773c0%return { + print("exit:", execname(), argevent) + } + +8. timer + + tick-1ms { + printf("time fired on one cpu\n"); + } + + profile-2s { + printf("time fired on every cpu\n"); + } + +More sample scripts can be found at scripts/ directory. + +## Mailing list + +You can subscribe to ktap mailing list at link (subscribe before posting): +http://www.freelists.org/list/ktap + + +## Copyright and License + +ktap is licensed under GPL v2 + +Copyright (C) 2012-2013, Jovi Zhangwei <[email protected]>. +All rights reserved. + + +## Contribution + +ktap is still under active development, so contributions are welcome. +You are encouraged to report bugs, provide feedback, send feature request, +or hack on it. + + +## See More + +More info can be found at [documentation][tutorial] +[tutorial]: http://www.ktap.org/doc/tutorial.html + diff --git a/drivers/staging/ktap/doc/tutorial.md b/drivers/staging/ktap/doc/tutorial.md new file mode 100644 index 000000000000..3c32ce77a731 --- /dev/null +++ b/drivers/staging/ktap/doc/tutorial.md @@ -0,0 +1,552 @@ +% The ktap Tutorial + +# Introduction + +ktap is a new scripting dynamic tracing tool for linux + +ktap is a new scripting dynamic tracing tool for Linux, +it uses a scripting language and lets users trace the Linux kernel dynamically. +ktap is designed to give operational insights with interoperability +that allows users to tune, troubleshoot and extend kernel and application. +It's similar with Linux Systemtap and Solaris Dtrace. + +ktap have different design principles from Linux mainstream dynamic tracing +language in that it's based on bytecode, so it doesn't depend upon GCC, +doesn't require compiling kernel module for each script, safe to use in +production environment, fulfilling the embedded ecosystem's tracing needs. + +Highlights features: + +* simple but powerful scripting language +* register based interpreter (heavily optimized) in Linux kernel +* small and lightweight (6KLOC of interpreter) +* not depend on gcc for each script running +* easy to use in embedded environment without debugging info +* support for tracepoint, kprobe, uprobe, function trace, timer, and more +* supported in x86, arm, ppc, mips +* safety in sandbox + + +# Getting started + +Requirements + +* Linux 3.1 or later(Need some kernel patches for kernel earlier than 3.1) +* CONFIG_EVENT_TRACING enabled +* CONFIG_PERF_EVENTS enabled +* CONFIG_DEBUG_FS enabled + (make sure debugfs mounted before insmod ktapvm + mount debugfs: mount -t debugfs none /sys/kernel/debug/) + +Note that those configuration is always enabled in Linux distribution, +like REHL, Fedora, Ubuntu, etc. + +1. Clone ktap from github + + $ git clone http://github.com/ktap/ktap.git + +2. Compiling ktap + + $ cd ktap + $ make #generate ktapvm kernel module and ktap binary + +3. Load ktapvm kernel module(make sure debugfs mounted) + + $ make load #need to be root or have sudo access + +4. Running ktap + + $ ./ktap scripts/helloworld.kp + + +# Language basics + +## Syntax basics + +ktap's syntax is design on the mind of C language syntax friendly, +to make it easy scripting by kernel developer. + +1. Variable declaration +The biggest syntax differences with C is that ktap is a dynamic typed +language, so you won't need add any variable type declaration, just +use the variable. + +2. function +All functions in ktap should use keyword "function" declaration + +3. comments +The comments of ktap is starting from '#', long comments doesn't support now. + +4. others +Don't need place any ';' at the ending of statement in ktap. +ktap use free syntax style, so you can choose to use the ';' or not. + +ktap use nil as NULL, the result of any number operate on nil is nil. + +ktap don't have array structure, also don't have any pointer operation. + +## Control structures + +ktap if/else is same as C language. + +There have two method of for-loop in ktap: + + for (i = init, limit, step) { body } + +this is same as below in C: + + for (i = init; i < limit; i += step) { body } + +The next for-loop method is: + + for (k, v in pairs(t)) { body } # looping all elements of table + +Note that ktap don't have "continue" keyword, but C does. + +## Date structures + +Associative array is heavily used in ktap, it's also called by table. + +table declaration: + + t = {} + +how to use table: + + t[1] = 1 + t[1] = "xxx" + t["key"] = 10 + t["key"] = "value" + + for (k, v in pairs(t)) { body } # looping all elements of table + + +# Built in functions and librarys + +## Built in functions + +**print (...)** +Receives any number of arguments, and prints their values, +print is not intended for formatted output, but only as a +quick way to show a value, typically for debugging. +For formatted output, use printf. + +**printf (fmt, ...)** +Similar with C printf, use for format string output. + +**pairs (t)** +Returns three values: the next function, the table t, and nil, +so that the construction +for (k,v in pairs(t)) { body } +will iterate over all key-value pairs of table t. + +**len (t) /len (s)** +If the argument is string, return length of string, +if the argument is table, return counts of table pairs. + +**in_interrupt ()** +checking is context is interrupt context + +**exit ()** +quit ktap executing, similar with exit syscall + +**pid ()** +return current process pid + +**execname ()** +return current process exec name string + +**cpu ()** +return current cpu id + +**arch ()** +return machine architecture, like x86, arm, etc. + +**kernel_v ()** +return Linux kernel version string, like 3.9, etc. + +**user_string (addr)** +Receive userspace address, read string from userspace, return string. + +**histogram (t)** +Receive table, output table histogram to user. + +**curr_task_info (offset, fetch_bytes)** +fetch value in field offset of task_struct structure, argument fetch_bytes +could be 4 or 8, if fetch_bytes is not given, default is 4. + +user may need to get field offset by gdb, for example: +gdb vmlinux +(gdb)p &(((struct task_struct *)0).prio) + +**print_backtrace ()** +print current task stack info + + +## Librarys + +### Kdebug Library + +**kdebug.probe_by_id (event_ids, eventfun)** + +This function is underly representation of high level tracing primitive. +event_ids is the id of all events, it's read from +/sys/kernel/debug/tracing/events/$SYS/$EVENT/id + +for multi-events tracing, the event_ids is concatenation of all id, for example: + "2 3 4", seperated by blank space. + +The second argument in above examples is a function: +function eventfun () { action } + + +**kdebug.probe_end (endfunc)** + +This function is used for invoking a function when tracing end, it will wait +until user press CTRL+C to stop tracing, then ktap will call endfunc function, +user could show tracing results in that function, or do other things. + + +### Timer Library + + + +# Linux tracing basics + +tracepoints, probe, timer +filters +above explaintion +Ring buffer + +# Tracing semantics in ktap + +## Tracing block + +**trace EVENTDEF /FILTER/ { ACTION }** + +This is the basic tracing block for ktap, you need to use a specific EVENTDEF +string, and own event function. + +EVENTDEF is compatible with perf(see perf-list), with glob match, for example: + + syscalls:* trace all syscalls events + syscalls:sys_enter_* trace all syscalls entry events + kmem:* trace all kmem related events + sched:* trace all sched related events + *:* trace all tracepoints in system. + +All events are based on: /sys/kernel/debug/tracing/events/$SYS/$EVENT + +**trace_end { ACTION }** + +This is based on kdebug.probe_end function. + +## Tracing built-in variable + +**argevent** +event object, you can print it by: print(argevent), it will print events +into human readable string, the result is mostly same as each entry of +/sys/kernel/debug/tracing/trace + +**argname** +event name, each event have a name associated with it. + +**arg1..9** +get argument 1..9 of event object. + + +## Timer syntax + +**tick-Ns { ACTION }** +**tick-Nsec { ACTION }** +**tick-Nms { ACTION }** +**tick-Nmsec { ACTION }** +**tick-Nus { ACTION }** +**tick-Nusec { ACTION }** + +**profile-Ns { ACTION }** +**profile-Nsec { ACTION }** +**profile-Nms { ACTION }** +**profile-Nmsec { ACTION }** +**profile-Nus { ACTION }** +**profile-Nusec { ACTION }** + +architecture overview picture reference(pnp format) +one-liners +simple event tracing + +# Advanced tracing pattern + +Aggregation/Histogram +thread local +flame graph + +# Overhead/Performance + +ktap have more fast boot time thant Systemtap(try the helloword script) +ktap have little memory usage than Systemtap +and some scripts show that ktap have a little overhead then Systemtap +(we choosed two scripts to compare, function profile, stack profile. +this is not means all scripts in Systemtap have big overhead than ktap) + + +# FAQ + +**Q: Why use bytecode design?** +A: Using bytecode would be a clean and lightweight solution, + you don't need gcc toolchain to compile every scripts, all you + need is a ktapvm kernel modules and userspace tool called ktap. + Since its language virtual machine design, it have great portability, + suppose you are working at a multi-arch cluster, if you want to run + a tracing script on each board, you won't need cross-compile tracing + script onto all board, what you really need to do is use ktap tool + to run script just in time. + + Bytecode based design also will make executing more safer, than native code + generation. + + Reality already showing that SystemTap is not widely used in embedded Linux, + caused by problem of SystemTap's architecture design choice, it's a natural + design for Redhat and IBM, because Redhat/IBM is focusing on server area, + not embedded area. + +**Q: What's the differences with SystemTap and Dtrace?** +A: For SystemTap, the answer is already mentioned at above question, + SystemTap use translator design, for trade-off on performance with usability, + based on GCC, that's what ktap want to solve. + + For Dtrace, one common design with Dtrace is also use bytecode, so basically + Dtrace and ktap is on the same road. There have some projects aim to porting + Dtrace from Solaris to Linux, but the process is still on the road, Dtrace + is rooted in Solaris, and there have many huge differences between Solaris + tracing infrastructure with Linux's. + + Dtrace is based on D language, a language subset of C, it's a restricted + language, like without for-looping, for safty use in production system. + It seems that Dtrace for Linux only support x86 architecture, not work on + powerpc and arm/mips, obviously it's not suit for embedded Linux currently. + + Dtrace use ctf as input for debuginfo handing, compare with vmlinux for + SystemTap. + + On the license part, Dtrace is released as CDDL, which is incompatible with + GPL(this is why it's impossible to upstream Dtrace into mainline). + +**Q: Why use dynamically typed language? but not statically typed language?** +A: It's hard to say which one is more better than other, dynamically typed + language bring efficiency and fast prototype production, but loosing type + check at compiling phase, and easy to make mistake in runtime, also it's + need many runtime checking, In contrast, statically typed language win on + programing safety, and performance. Statically language would suit for + interoperate with kernel, as kernel is wrote mainly in C, Need to note that + SystemTap and Dtrace both is statically language. + + ktap choose dynamically typed language as initial implementation. + +**Q: Why we need ktap for event tracing? There already have a built-in ftrace** +A: This also is a common question for all dynamic tracing tool, not only ktap. + ktap provide more flexibility than built-in tracing infrastructure. Suppose + you need print a global variable when tracepoint hit, or you want print + backtrace, even more, you want to store some info into associative array, and + display it in histogram style when tracing end, in these case, some of them + ftrace can take it, some of them ftrace can not. + Overall, ktap provide you with great flexibility to scripting your own trace + need. + +**Q: How about the performance? Is ktap slow?** +A: ktap is not slow, the bytecode is very high-level, based on lua, the language + virtual machine is register-based(compare with stack-based), with little + instruction, the table data structure is heavily optimized in ktapvm. + ktap use per-cpu allocation in many place, without global locking scheme, + it's very fast when executing tracepoint callback. + Performance benchmark showing that the overhead of ktap running is nearly + 10%(store event name into associative array), compare with full speed + running without any tracepoint enabled. + + ktap will optimize overhead all the time, hopefully the overhead will + decrease to little than 5%, even more. + +**Q: Why not porting a high level language implementation into kernel directly? + Like python/JVM?** +A: I take serious on the size of vm and memory footprint. Python vm is large, + it's not suit to embed into kernel, and python have some functionality + which we don't need. + + The bytecode of other high level language is also big, ktap only have 32 + bytecodes, python/java/erlang have nearly two hundred bytecodes. + There also have some problems when porting those language into kernel, + userspace programming have many differences with kernel programming, + like float numbers, handle sleeping code carefully in kernel, deadloop is + not allowed in kernel, multi-thread management, etc.., so it's impossible + to porting language implementation into kernel with little adaption work. + +**Q: What's the status of ktap now?** +A: Basically it works on x86-32, x86-64, powerpc, arm, it also could work for + other hardware architecture, but not proven yet(I don't have enough hardware + to test) + If you found some bug, fix it on you own programming skill, or report to me. + +**Q: How to hack ktap? I want to write some extensions onto ktap.** +A: welcome hacking. + You can write your own library to fulfill your specific need, + you can write any script as you want. + +**Q: What's the plan of ktap? any roadmap?** +A: the current plan is deliver stable ktapvm kernel modules, more ktap script, + and bugfix. + + +# References + +* [Linux Performance Analysis and Tools][LPAT] +* [Dtrace Blog][dtraceblog] +* [Dtrace User Guide][dug] +* [LWN: ktap -- yet another kernel tracer][lwn] +* [ktap introduction in LinuxCon Japan 2013][lcj] + +[LPAT]: http://www.brendangregg.com/Slides/SCaLE_Linux_Performance2013.pdf +[dtraceblog]: http://dtrace.org/blogs/ +[dug]: http://docs.huihoo.com/opensolaris/dtrace-user-guide/html/index.html +[lwn]: http://lwn.net/Articles/551314/ +[lcj]: http://events.linuxfoundation.org/sites/events/files/lcjpcojp13_zhangwei.pdf + + +# History + +* ktap was invented at 2002 +* First RFC sent to LKML at 2012.12.31 +* The code was released in github at 2013.01.18 +* ktap released v0.1 at 2013.05.21 +* ktap released v0.2 at 2013.07.31 + +For more release info, please look at RELEASES.txt in project root directory. + +# Sample scripts + +1. simplest one-liner command to enable all tracepoints + + ktap -e "trace *:* { print(argevent) }" + +2. syscall tracing on target process + + ktap -e "trace syscalls:* { print(argevent) }" -- ls + +3. function tracing + + ktap -e "trace ftrace:function { print(argevent) }" + + ktap -e "trace ftrace:function /ip==mutex*/ { print(argevent) }" + +4. simple syscall tracing + + trace syscalls:* { + print(cpu(), pid(), execname(), argevent) + } + +5. syscall tracing in histogram style + + s = {} + + trace syscalls:sys_enter_* { + s[argname] += 1 + } + + trace_end { + histogram(s) + } + +6. kprobe tracing + + trace probe:do_sys_open dfd=%di fname=%dx flags=%cx mode=+4($stack) { + print("entry:", execname(), argevent) + } + + trace probe:do_sys_open%return fd=$retval { + print("exit:", execname(), argevent) + } + +7. uprobe tracing + + trace probe:/lib/libc.so.6:0x000773c0 { + print("entry:", execname(), argevent) + } + + trace probe:/lib/libc.so.6:0x000773c0%return { + print("exit:", execname(), argevent) + } + +8. timer + + tick-1ms { + printf("time fired on one cpu\n"); + } + + profile-2s { + printf("time fired on every cpu\n"); + } + +More sample scripts can be found at scripts/ directory. + + +# Appendix + +Here is the complete syntax of ktap in extended BNF. +(based on lua syntax: http://www.lua.org/manual/5.1/manual.html#5.1) + + chunk ::= {stat [';']} [laststat [';'] + + block ::= chunk + + stat ::= varlist '=' explist | + functioncall | + { block } | + while exp { block } | + repeat block until exp | + if exp { block {elseif exp { block }} [else block] } | + for Name '=' exp ',' exp [',' exp] { block } | + for namelist in explist { block } | + function funcname funcbody | + local function Name funcbody | + local namelist ['=' explist] + + laststat ::= return [explist] | break + + funcname ::= Name {'.' Name} [':' Name] + + varlist ::= var {',' var} + + var ::= Name | prefixexp '[' exp ']'| prefixexp '.' Name + + namelist ::= Name {',' Name} + + explist ::= {exp ',' exp + + exp ::= nil | false | true | Number | String | '...' | function | + prefixexp | tableconstructor | exp binop exp | unop exp + + prefixexp ::= var | functioncall | '(' exp ')' + + functioncall ::= prefixexp args | prefixexp ':' Name args + + args ::= '(' [explist] ')' | tableconstructor | String + + function ::= function funcbody + + funcbody ::= '(' [parlist] ')' { block } + + parlist ::= namelist [',' '...'] | '...' + + tableconstructor ::= '{' [fieldlist] '}' + + fieldlist ::= field {fieldsep field} [fieldsep] + + field ::= '[' exp ']' '=' exp | Name '=' exp | exp + + fieldsep ::= ',' | ';' + + binop ::= '+' | '-' | '*' | '/' | '^' | '%' | '..' | + '<' | '<=' | '>' | '>=' | '==' | '!=' | + and | or + + unop ::= '-' + diff --git a/drivers/staging/ktap/include/ktap.h b/drivers/staging/ktap/include/ktap.h new file mode 100644 index 000000000000..076dd4aa6477 --- /dev/null +++ b/drivers/staging/ktap/include/ktap.h @@ -0,0 +1,169 @@ +#ifndef __KTAP_H__ +#define __KTAP_H__ + +#include "ktap_types.h" +#include "ktap_opcodes.h" + +#include <linux/version.h> +#include <linux/hardirq.h> +#include <linux/perf_event.h> +#include <linux/trace_seq.h> + +typedef struct ktap_Reg { + const char *name; + ktap_cfunction func; +} ktap_Reg; + +struct ktap_probe_event { + struct list_head list; + struct perf_event *perf; + ktap_state *ks; + ktap_closure *cl; +}; + +/* this structure allocate on stack */ +struct ktap_event { + struct ktap_probe_event *pevent; + struct ftrace_event_call *call; + struct trace_entry *entry; + int entry_size; + struct pt_regs *regs; +}; + +enum { + KTAP_PERCPU_DATA_STATE, + KTAP_PERCPU_DATA_STACK, + KTAP_PERCPU_DATA_BUFFER, + KTAP_PERCPU_DATA_BUFFER2, + KTAP_PERCPU_DATA_BTRACE, + + KTAP_PERCPU_DATA_MAX +}; + +#define KTAP_PERCPU_BUFFER_SIZE (3 * PAGE_SIZE) + +int gettimeofday_us(void); +ktap_state *kp_newstate(struct ktap_parm *parm, struct dentry *dir); +void kp_exit(ktap_state *ks); +void kp_final_exit(ktap_state *ks); +ktap_state *kp_newthread(ktap_state *mainthread); +void kp_exitthread(ktap_state *ks); +ktap_closure *kp_load(ktap_state *ks, unsigned char *buff); +void kp_call(ktap_state *ks, StkId func, int nresults); +void kp_optimize_code(ktap_state *ks, int level, ktap_proto *f); +void kp_register_lib(ktap_state *ks, const char *libname, const ktap_Reg *funcs); +void *kp_percpu_data(int type); + +void kp_init_baselib(ktap_state *ks); +void kp_init_oslib(ktap_state *ks); +void kp_init_kdebuglib(ktap_state *ks); +void kp_init_timerlib(ktap_state *ks); +void kp_init_ansilib(ktap_state *ks); + +int kp_probe_init(ktap_state *ks); +void kp_probe_exit(ktap_state *ks); + +void kp_perf_event_register(ktap_state *ks, struct perf_event_attr *attr, + struct task_struct *task, char *filter, + ktap_closure *cl); + +void kp_event_getarg(ktap_state *ks, ktap_value *ra, int n); +void kp_event_tostring(ktap_state *ks, struct trace_seq *seq); + +int kp_strfmt(ktap_state *ks, struct trace_seq *seq); + +void kp_transport_write(ktap_state *ks, const void *data, size_t length); +void kp_transport_event_write(ktap_state *ks, struct ktap_event *e); +void kp_transport_print_backtrace(ktap_state *ks); +void *kp_transport_reserve(ktap_state *ks, size_t length); +void kp_transport_exit(ktap_state *ks); +int kp_transport_init(ktap_state *ks, struct dentry *dir); + +void kp_exit_timers(ktap_state *ks); + +extern int kp_max_exec_count; + +/* get from kernel/trace/trace.h */ +static __always_inline int trace_get_context_bit(void) +{ + int bit; + + if (in_interrupt()) { + if (in_nmi()) + bit = 0; + else if (in_irq()) + bit = 1; + else + bit = 2; + } else + bit = 3; + + return bit; +} + +/* use a special timer context kp_state instead use this recursion approach? */ +DECLARE_PER_CPU(int, kp_recursion_context[PERF_NR_CONTEXTS]); + +static __always_inline int get_recursion_context(void) +{ + int rctx = trace_get_context_bit(); + + if (__this_cpu_read(kp_recursion_context[rctx])) + return -1; + + __this_cpu_write(kp_recursion_context[rctx], true); + barrier(); + + return rctx; +} + +static inline void put_recursion_context(int rctx) +{ + barrier(); + __this_cpu_write(kp_recursion_context[rctx], false); +} + + +extern unsigned int kp_stub_exit_instr; + +static inline void set_next_as_exit(ktap_state *ks) +{ + ktap_callinfo *ci; + + ci = ks->ci; + if (!ci) + return; + + ci->u.l.savedpc = &kp_stub_exit_instr; + + /* See precall, ci changed to ci->prev after invoke C function */ + if (ci->prev) { + ci = ci->prev; + ci->u.l.savedpc = &kp_stub_exit_instr; + } +} + +#define kp_verbose_printf(ks, ...) \ + if (G(ks)->parm->verbose) \ + kp_printf(ks, "[verbose] "__VA_ARGS__); + +/* get argument operation macro */ +#define kp_arg(ks, n) ((ks)->ci->func + (n)) +#define kp_arg_nr(ks) ((int)(ks->top - (ks->ci->func + 1))) + +#define kp_arg_check(ks, narg, type) \ + do { \ + if (unlikely(ttypenv(kp_arg(ks, narg)) != type)) { \ + kp_error(ks, "wrong type of argument %d\n", narg);\ + return -1; \ + } \ + } while (0) + + +#if LINUX_VERSION_CODE > KERNEL_VERSION(3, 5, 0) +#define SPRINT_SYMBOL sprint_symbol_no_offset +#else +#define SPRINT_SYMBOL sprint_symbol +#endif + +#endif /* __KTAP_H__ */ diff --git a/drivers/staging/ktap/include/ktap_opcodes.h b/drivers/staging/ktap/include/ktap_opcodes.h new file mode 100644 index 000000000000..31c558b680f4 --- /dev/null +++ b/drivers/staging/ktap/include/ktap_opcodes.h @@ -0,0 +1,240 @@ +#ifndef __KTAP_BYTECODE_H__ +#define __KTAP_BYTECODE_H__ + + +/* opcode is copied from lua initially */ + +typedef enum { +/*---------------------------------------------------------------------- + * name args description + * ------------------------------------------------------------------------*/ +OP_MOVE,/* A B R(A) := R(B) */ +OP_LOADK,/* A Bx R(A) := Kst(Bx) */ +OP_LOADKX,/* A R(A) := Kst(extra arg) */ +OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */ +OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */ +OP_GETUPVAL,/* A B R(A) := UpValue[B] */ + +OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */ +OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */ + +OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */ +OP_SETTABUP_INCR,/* A B C UpValue[A][RK(B)] += RK(C) */ +OP_SETUPVAL,/* A B UpValue[B] := R(A) */ +OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */ +OP_SETTABLE_INCR,/* A B C R(A)[RK(B)] += RK(C) */ + +OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */ + +OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */ + +OP_ADD,/* A B C R(A) := RK(B) + RK(C) */ +OP_SUB,/* A B C R(A) := RK(B) - RK(C) */ +OP_MUL,/* A B C R(A) := RK(B) * RK(C) */ +OP_DIV,/* A B C R(A) := RK(B) / RK(C) */ +OP_MOD,/* A B C R(A) := RK(B) % RK(C) */ +OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */ +OP_UNM,/* A B R(A) := -R(B) */ +OP_NOT,/* A B R(A) := not R(B) */ +OP_LEN,/* A B R(A) := length of R(B) */ + +OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ + +OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A) + 1 */ +OP_EQ,/* A B C if ((RK(B) == RK(C)) != A) then pc++ */ +OP_LT,/* A B C if ((RK(B) < RK(C)) != A) then pc++ */ +OP_LE,/* A B C if ((RK(B) <= RK(C)) != A) then pc++ */ + +OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ + +OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ + +OP_FORLOOP,/* A sBx R(A)+=R(A+2); + if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/ +OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */ + +OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */ +OP_TFORLOOP,/* A sBx if R(A+1) != nil then { R(A)=R(A+1); pc += sBx }*/ + +OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */ + +OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */ + +OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */ + +OP_EXTRAARG,/* Ax extra (larger) argument for previous opcode */ + +OP_EVENT,/* A B C R(A) := R(B)[C] */ + +OP_EVENTNAME, /* A R(A) = event_name() */ + +OP_EVENTARG,/* A B R(A) := event_arg(B)*/ + +OP_LOAD_GLOBAL,/* A B C R(A) := R(B)[C] */ + +OP_EXIT, + +} OpCode; + + +#define NUM_OPCODES ((int)OP_LOAD_GLOBAL + 1) + + +enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ + + +/* + * ** size and position of opcode arguments. + * */ +#define SIZE_C 9 +#define SIZE_B 9 +#define SIZE_Bx (SIZE_C + SIZE_B) +#define SIZE_A 8 +#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) + +#define SIZE_OP 6 + +#define POS_OP 0 +#define POS_A (POS_OP + SIZE_OP) +#define POS_C (POS_A + SIZE_A) +#define POS_B (POS_C + SIZE_C) +#define POS_Bx POS_C +#define POS_Ax POS_A + + + +/* + * ** limits for opcode arguments. + * ** we use (signed) int to manipulate most arguments, + * ** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) + * */ +#define MAXARG_Bx ((1<<SIZE_Bx)-1) +#define MAXARG_sBx (MAXARG_Bx>>1) /* `sBx' is signed */ + +#define MAXARG_Ax ((1<<SIZE_Ax)-1) + +#define MAXARG_A ((1<<SIZE_A)-1) +#define MAXARG_B ((1<<SIZE_B)-1) +#define MAXARG_C ((1<<SIZE_C)-1) + + +/* creates a mask with `n' 1 bits at position `p' */ +#define MASK1(n,p) ((~((~(ktap_instruction)0)<<(n)))<<(p)) + +/* creates a mask with `n' 0 bits at position `p' */ +#define MASK0(n,p) (~MASK1(n,p)) + +/* + * ** the following macros help to manipulate instructions + * */ + +#define GET_OPCODE(i) ((OpCode)((i)>>POS_OP) & MASK1(SIZE_OP,0)) +#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ + ((((ktap_instruction)o)<<POS_OP)&MASK1(SIZE_OP,POS_OP)))) + +#define getarg(i,pos,size) ((int)((i)>>pos) & MASK1(size,0)) +#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ + ((((ktap_instruction)v)<<pos)&MASK1(size,pos)))) + +#define GETARG_A(i) getarg(i, POS_A, SIZE_A) +#define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A) + +#define GETARG_A(i) getarg(i, POS_A, SIZE_A) +#define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A) + +#define GETARG_B(i) getarg(i, POS_B, SIZE_B) +#define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B) + +#define GETARG_C(i) getarg(i, POS_C, SIZE_C) +#define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C) + +#define GETARG_Bx(i) getarg(i, POS_Bx, SIZE_Bx) +#define SETARG_Bx(i,v) setarg(i, v, POS_Bx, SIZE_Bx) + +#define GETARG_Ax(i) getarg(i, POS_Ax, SIZE_Ax) +#define SETARG_Ax(i,v) setarg(i, v, POS_Ax, SIZE_Ax) + +#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx) +#define SETARG_sBx(i,b) SETARG_Bx((i), (unsigned int)(b)+MAXARG_sBx) + +#define CREATE_ABC(o,a,b,c) (((ktap_instruction)(o))<<POS_OP) \ + | (((ktap_instruction)(a))<<POS_A) \ + | (((ktap_instruction)(b))<<POS_B) \ + | (((ktap_instruction)(c))<<POS_C) + +#define CREATE_ABx(o,a,bc) (((ktap_instruction)(o))<<POS_OP) \ + | (((ktap_instruction)(a))<<POS_A) \ + | (((ktap_instruction)(bc))<<POS_Bx) + +#define CREATE_Ax(o,a) (((ktap_instruction)(o))<<POS_OP) \ + | (((ktap_instruction)(a))<<POS_Ax) + + + +/* + * ** Macros to operate RK indices + * */ + +/* this bit 1 means constant (0 means register) */ +#define BITRK (1 << (SIZE_B - 1)) + +/* test whether value is a constant */ +#define ISK(x) ((x) & BITRK) + +/* gets the index of the constant */ +#define INDEXK(r) ((int)(r) & ~BITRK) + +#define MAXINDEXRK (BITRK - 1) + +/* code a constant index as a RK value */ +#define RKASK(x) ((x) | BITRK) + + +/* + * ** invalid register that fits in 8 bits + * */ +#define NO_REG MAXARG_A + + +/* + * ** R(x) - register + * ** Kst(x) - constant (in constant table) + * ** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x) + * */ + + + +/* + * ** masks for instruction properties. The format is: + * ** bits 0-1: op mode + * ** bits 2-3: C arg mode + * ** bits 4-5: B arg mode + * ** bit 6: instruction set register A + * ** bit 7: operator is a test (next instruction must be a jump) + * */ + +enum OpArgMask { + OpArgN, /* argument is not used */ + OpArgU, /* argument is used */ + OpArgR, /* argument is a register or a jump offset */ + OpArgK /* argument is a constant or register/constant */ +}; + +extern const u8 ktap_opmodes[NUM_OPCODES]; + +#define getOpMode(m) ((enum OpMode)ktap_opmodes[m] & 3) +#define getBMode(m) ((enum OpArgMask)(ktap_opmodes[m] >> 4) & 3) +#define getCMode(m) ((enum OpArgMask)(ktap_opmodes[m] >> 2) & 3) +#define testAMode(m) (ktap_opmodes[m] & (1 << 6)) +#define testTMode(m) (ktap_opmodes[m] & (1 << 7)) + + +/* number of list items to accumulate before a SETLIST instruction */ +#define LFIELDS_PER_FLUSH 50 + +extern const char *const ktap_opnames[NUM_OPCODES + 1]; + +#endif /* __KTAP_BYTECODE_H__ */ diff --git a/drivers/staging/ktap/include/ktap_types.h b/drivers/staging/ktap/include/ktap_types.h new file mode 100644 index 000000000000..cf1cef41b584 --- /dev/null +++ b/drivers/staging/ktap/include/ktap_types.h @@ -0,0 +1,674 @@ +#ifndef __KTAP_TYPES_H__ +#define __KTAP_TYPES_H__ + +/* opcode is copied from lua initially */ + +#ifdef __KERNEL__ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/semaphore.h> +#include <linux/wait.h> +#else +typedef char u8; +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#endif + +typedef struct ktap_parm { + char *trunk; /* __user */ + int trunk_len; + int argc; + char **argv; /* __user */ + int verbose; + int trace_pid; + int workload; + int trace_cpu; + int print_timestamp; +} ktap_parm; + +/* + * Ioctls that can be done on a ktap fd: + * todo: use _IO macro in include/uapi/asm-generic/ioctl.h + */ +#define KTAP_CMD_IOC_VERSION ('$' + 0) +#define KTAP_CMD_IOC_RUN ('$' + 1) +#define KTAP_CMD_IOC_EXIT ('$' + 3) + +#define KTAP_ENV "_ENV" + +#define KTAP_VERSION_MAJOR "0" +#define KTAP_VERSION_MINOR "2" + +#define KTAP_VERSION "ktap " KTAP_VERSION_MAJOR "." KTAP_VERSION_MINOR +#define KTAP_AUTHOR "Jovi Zhangwei <[email protected]>" +#define KTAP_COPYRIGHT KTAP_VERSION " Copyright (C) 2012-2013, " KTAP_AUTHOR + +#define MYINT(s) (s[0] - '0') +#define VERSION (MYINT(KTAP_VERSION_MAJOR) * 16 + MYINT(KTAP_VERSION_MINOR)) +#define FORMAT 0 /* this is the official format */ + +#define KTAP_SIGNATURE "\033ktap" + +/* data to catch conversion errors */ +#define KTAPC_TAIL "\x19\x93\r\n\x1a\n" + +/* size in bytes of header of binary files */ +#define KTAPC_HEADERSIZE (sizeof(KTAP_SIGNATURE) - sizeof(char) + 2 + \ + 6 + sizeof(KTAPC_TAIL) - sizeof(char)) + +typedef int ktap_instruction; + +typedef union ktap_gcobject ktap_gcobject; + +#define CommonHeader ktap_gcobject *next; u8 tt; + +struct ktap_state; +typedef int (*ktap_cfunction) (struct ktap_state *ks); + +typedef union ktap_string { + int dummy; /* ensures maximum alignment for strings */ + struct { + CommonHeader; + u8 extra; /* reserved words for short strings; "has hash" for longs */ + unsigned int hash; + size_t len; /* number of characters in string */ + } tsv; +} ktap_string; + +#define getstr(ts) (const char *)((ts) + 1) +#define eqshrstr(a,b) ((a) == (b)) + +#define svalue(o) getstr(rawtsvalue(o)) + + +union _ktap_value { + ktap_gcobject *gc; /* collectable objects */ + void *p; /* light userdata */ + int b; /* booleans */ + ktap_cfunction f; /* light C functions */ + long n; /* numbers */ +}; + + +typedef struct ktap_value { + union _ktap_value val; + int type; +} ktap_value; + +typedef ktap_value * StkId; + + + +typedef union ktap_udata { + struct { + CommonHeader; + size_t len; /* number of bytes */ + } uv; +} ktap_udata; + +/* + * Description of an upvalue for function prototypes + */ +typedef struct ktap_upvaldesc { + ktap_string *name; /* upvalue name (for debug information) */ + u8 instack; /* whether it is in stack */ + u8 idx; /* index of upvalue (in stack or in outer function's list) */ +} ktap_upvaldesc; + +/* + * Description of a local variable for function prototypes + * (used for debug information) + */ +typedef struct ktap_locvar { + ktap_string *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} ktap_locvar; + + +typedef struct ktap_upval { + CommonHeader; + ktap_value *v; /* points to stack or to its own value */ + union { + ktap_value value; /* the value (when closed) */ + struct { /* double linked list (when open) */ + struct ktap_upval *prev; + struct ktap_upval *next; + } l; + } u; +} ktap_upval; + + +#define KTAP_STACK_MAX_ENTRIES 10 + +typedef struct ktap_btrace { + CommonHeader; + unsigned int nr_entries; + unsigned long entries[KTAP_STACK_MAX_ENTRIES]; +} ktap_btrace; + +#define ktap_closure_header \ + CommonHeader; u8 nupvalues; ktap_gcobject *gclist + +typedef struct ktap_cclosure { + ktap_closure_header; + ktap_cfunction f; + ktap_value upvalue[1]; /* list of upvalues */ +} ktap_cclosure; + + +typedef struct ktap_lclosure { + ktap_closure_header; + struct ktap_proto *p; + struct ktap_upval *upvals[1]; /* list of upvalues */ +} ktap_lclosure; + + +typedef struct ktap_closure { + struct ktap_cclosure c; + struct ktap_lclosure l; +} ktap_closure; + + +typedef struct ktap_proto { + CommonHeader; + ktap_value *k; /* constants used by the function */ + ktap_instruction *code; + struct ktap_proto **p; /* functions defined inside the function */ + int *lineinfo; /* map from opcodes to source lines (debug information) */ + struct ktap_locvar *locvars; /* information about local variables (debug information) */ + struct ktap_upvaldesc *upvalues; /* upvalue information */ + ktap_closure *cache; /* last created closure with this prototype */ + ktap_string *source; /* used for debug information */ + int sizeupvalues; /* size of 'upvalues' */ + int sizek; /* size of `k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of `p' */ + int sizelocvars; + int linedefined; + int lastlinedefined; + u8 numparams; /* number of fixed parameters */ + u8 is_vararg; + u8 maxstacksize; /* maximum stack used by this function */ +} ktap_proto; + + +/* + * information about a call + */ +typedef struct ktap_callinfo { + StkId func; /* function index in the stack */ + StkId top; /* top for this function */ + struct ktap_callinfo *prev, *next; /* dynamic call link */ + short nresults; /* expected number of results from this function */ + u8 callstatus; + int extra; + union { + struct { /* only for Lua functions */ + StkId base; /* base for this function */ + const unsigned int *savedpc; + } l; + struct { /* only for C functions */ + int ctx; /* context info. in case of yields */ + u8 status; + } c; + } u; +} ktap_callinfo; + + +/* + * ktap_tables + */ +typedef union ktap_tkey { + struct { + union _ktap_value value_; + int tt_; + struct ktap_tnode *next; /* for chaining */ + } nk; + ktap_value tvk; +} ktap_tkey; + + +typedef struct ktap_tnode { + ktap_value i_val; + ktap_tkey i_key; +} ktap_tnode; + + +typedef struct ktap_table { + CommonHeader; +#ifdef __KERNEL__ + arch_spinlock_t lock; +#endif + u8 flags; /* 1<<p means tagmethod(p) is not present */ + u8 lsizenode; /* log2 of size of `node' array */ + int sizearray; /* size of `array' array */ + ktap_value *array; /* array part */ + ktap_tnode *node; + ktap_tnode *lastfree; /* any free position is before this position */ + ktap_gcobject *gclist; +} ktap_table; + +#define lmod(s,size) ((int)((s) & ((size)-1))) + +enum AGGREGATION_TYPE { + AGGREGATION_TYPE_COUNT, + AGGREGATION_TYPE_MAX, + AGGREGATION_TYPE_MIN, + AGGREGATION_TYPE_SUM, + AGGREGATION_TYPE_AVG +}; + +typedef struct ktap_aggrtable { + CommonHeader; + ktap_table **pcpu_tbl; + ktap_gcobject *gclist; +} ktap_aggrtable; + +typedef struct ktap_aggraccval { + CommonHeader; + int type; + int val; + int more; +} ktap_aggraccval; + +typedef struct ktap_stringtable { + ktap_gcobject **hash; + int nuse; + int size; +} ktap_stringtable; + +typedef struct ktap_global_state { + ktap_stringtable strt; /* hash table for strings */ + ktap_value registry; + unsigned int seed; /* randonized seed for hashes */ + u8 gcstate; /* state of garbage collector */ + u8 gckind; /* kind of GC running */ + u8 gcrunning; /* true if GC is running */ + + ktap_gcobject *allgc; /* list of all collectable objects */ + + ktap_upval uvhead; /* head of double-linked list of all open upvalues */ + + struct ktap_state *mainthread; +#ifdef __KERNEL__ + ktap_parm *parm; + pid_t trace_pid; + struct task_struct *trace_task; + cpumask_var_t cpumask; + struct ring_buffer *buffer; + struct dentry *trace_pipe_dentry; + int nr_builtin_cfunction; + ktap_value *cfunction_tbl; + struct task_struct *task; + int trace_enabled; + struct list_head timers; + struct list_head probe_events_head; + int exit; + int wait_user; + ktap_closure *trace_end_closure; +#endif + int error; +} ktap_global_state; + +typedef struct ktap_state { + CommonHeader; + u8 status; + ktap_global_state *g; + int stop; + StkId top; + ktap_callinfo *ci; + const unsigned long *oldpc; + StkId stack_last; + StkId stack; + int stacksize; + ktap_gcobject *openupval; + ktap_callinfo baseci; + + int debug; + int version; + int gcrunning; + + /* list of temp collectable objects, free when thread exit */ + ktap_gcobject *gclist; + +#ifdef __KERNEL__ + struct ktap_event *current_event; + int aggr_accval; /* for temp value storage */ +#endif +} ktap_state; + + +typedef struct gcheader { + CommonHeader; +} gcheader; + +/* + * Union of all collectable objects + */ +union ktap_gcobject { + gcheader gch; /* common header */ + union ktap_string ts; + union ktap_udata u; + struct ktap_closure cl; + struct ktap_table h; + struct ktap_aggrtable ah; + struct ktap_aggraccval acc; + struct ktap_proto p; + struct ktap_upval uv; + struct ktap_state th; /* thread */ + struct ktap_btrace bt; /* thread */ +}; + +#define gch(o) (&(o)->gch) +/* macros to convert a GCObject into a specific value */ +#define rawgco2ts(o) (&((o)->ts)) +#define gco2ts(o) (&rawgco2ts(o)->tsv) + +#define gco2uv(o) (&((o)->uv)) + +#define obj2gco(v) ((ktap_gcobject *)(v)) + + +#ifdef __KERNEL__ +#define ktap_assert(s) +#else +#define ktap_assert(s) +#if 0 +#define ktap_assert(s) \ + do { \ + if (!s) { \ + printf("assert failed %s, %d\n", __func__, __LINE__);\ + exit(0); \ + } \ + } while(0) +#endif +#endif + +#define check_exp(c,e) (e) + + +typedef int ktap_number; + + +#define ktap_number2int(i,n) ((i)=(int)(n)) + + +/* predefined values in the registry */ +#define KTAP_RIDX_MAINTHREAD 1 +#define KTAP_RIDX_GLOBALS 2 +#define KTAP_RIDX_LAST KTAP_RIDX_GLOBALS + + +#define KTAP_TNONE (-1) + +#define KTAP_TNIL 0 +#define KTAP_TBOOLEAN 1 +#define KTAP_TLIGHTUSERDATA 2 +#define KTAP_TNUMBER 3 +#define KTAP_TSTRING 4 +#define KTAP_TSHRSTR (KTAP_TSTRING | (0 << 4)) /* short strings */ +#define KTAP_TLNGSTR (KTAP_TSTRING | (1 << 4)) /* long strings */ +#define KTAP_TTABLE 5 +#define KTAP_TFUNCTION 6 +#define KTAP_TLCL (KTAP_TFUNCTION | (0 << 4)) /* closure */ +#define KTAP_TLCF (KTAP_TFUNCTION | (1 << 4)) /* light C function */ +#define KTAP_TCCL (KTAP_TFUNCTION | (2 << 4)) /* C closure */ +#define KTAP_TUSERDATA 7 +#define KTAP_TTHREAD 8 + +#define KTAP_NUMTAGS 9 + +#define KTAP_TPROTO 11 +#define KTAP_TUPVAL 12 + +#define KTAP_TEVENT 13 + +#define KTAP_TBTRACE 14 + +#define KTAP_TAGGRTABLE 15 +#define KTAP_TAGGRACCVAL 16 +#define KTAP_TAGGRVAL 17 + +#define ttype(o) ((o->type) & 0x3F) +#define settype(obj, t) ((obj)->type = (t)) + + + +/* raw type tag of a TValue */ +#define rttype(o) ((o)->type) + +/* tag with no variants (bits 0-3) */ +#define novariant(x) ((x) & 0x0F) + +/* type tag of a TValue with no variants (bits 0-3) */ +#define ttypenv(o) (novariant(rttype(o))) + +#define val_(o) ((o)->val) + +#define bvalue(o) (val_(o).b) +#define nvalue(o) (val_(o).n) +#define hvalue(o) (&val_(o).gc->h) +#define ahvalue(o) (&val_(o).gc->ah) +#define aggraccvalue(o) (&val_(o).gc->acc) +#define CLVALUE(o) (&val_(o).gc->cl.l) +#define clcvalue(o) (&val_(o).gc->cl.c) +#define clvalue(o) (&val_(o).gc->cl) +#define rawtsvalue(o) (&val_(o).gc->ts) +#define pvalue(o) (&val_(o).p) +#define fvalue(o) (val_(o).f) +#define rawuvalue(o) (&val_(o).gc->u) +#define uvalue(o) (&rawuvalue(o)->uv) +#define evalue(o) (val_(o).p) +#define btvalue(o) (&val_(o).gc->bt) + +#define gcvalue(o) (val_(o).gc) + +#define isnil(o) (o->type == KTAP_TNIL) +#define isboolean(o) (o->type == KTAP_TBOOLEAN) +#define isfalse(o) (isnil(o) || (isboolean(o) && bvalue(o) == 0)) + +#define ttisshrstring(o) ((o)->type == KTAP_TSHRSTR) +#define ttisstring(o) (((o)->type & 0x0F) == KTAP_TSTRING) +#define ttisnumber(o) ((o)->type == KTAP_TNUMBER) +#define ttisfunc(o) ((o)->type == KTAP_TFUNCTION) +#define ttistable(o) ((o)->type == KTAP_TTABLE) +#define ttisaggrtable(o) ((o)->type == KTAP_TAGGRTABLE) +#define ttisaggrval(o) ((o)->type == KTAP_TAGGRVAL) +#define ttisaggracc(o) ((o)->type == KTAP_TAGGRACCVAL) +#define ttisnil(o) ((o)->type == KTAP_TNIL) +#define ttisboolean(o) ((o)->type == KTAP_TBOOLEAN) +#define ttisequal(o1,o2) ((o1)->type == (o2)->type) +#define ttisevent(o) ((o)->type == KTAP_TEVENT) +#define ttisbtrace(o) ((o)->type == KTAP_TBTRACE) + +#define ttisclone(o) ttisbtrace(o) + + +#define setnilvalue(obj) \ + { ktap_value *io = (obj); io->val.n = 0; settype(io, KTAP_TNIL); } + +#define setbvalue(obj, x) \ + { ktap_value *io = (obj); io->val.b = (x); settype(io, KTAP_TBOOLEAN); } + +#define setnvalue(obj, x) \ + { ktap_value *io = (obj); io->val.n = (x); settype(io, KTAP_TNUMBER); } + +#define setaggrvalue(obj, x) \ + { ktap_value *io = (obj); io->val.n = (x); settype(io, KTAP_TAGGRVAL); } + +#define setaggraccvalue(obj,x) \ + { ktap_value *io=(obj); \ + val_(io).gc = (ktap_gcobject *)(x); settype(io, KTAP_TAGGRACCVAL); } + +#define setsvalue(obj, x) \ + { ktap_value *io = (obj); \ + ktap_string *x_ = (x); \ + io->val.gc = (ktap_gcobject *)x_; settype(io, x_->tsv.tt); } + +#define setcllvalue(obj, x) \ + { ktap_value *io = (obj); \ + io->val.gc = (ktap_gcobject *)x; settype(io, KTAP_TLCL); } + +#define sethvalue(obj,x) \ + { ktap_value *io=(obj); \ + val_(io).gc = (ktap_gcobject *)(x); settype(io, KTAP_TTABLE); } + +#define setahvalue(obj,x) \ + { ktap_value *io=(obj); \ + val_(io).gc = (ktap_gcobject *)(x); settype(io, KTAP_TAGGRTABLE); } + +#define setfvalue(obj,x) \ + { ktap_value *io=(obj); val_(io).f=(x); settype(io, KTAP_TLCF); } + +#define setthvalue(L,obj,x) \ + { ktap_value *io=(obj); \ + val_(io).gc = (ktap_gcobject *)(x); settype(io, KTAP_TTHREAD); } + +#define setevalue(obj, x) \ + { ktap_value *io=(obj); val_(io).p = (x); settype(io, KTAP_TEVENT); } + +#define setbtvalue(obj,x) \ + { ktap_value *io=(obj); \ + val_(io).gc = (ktap_gcobject *)(x); settype(io, KTAP_TBTRACE); } + +#define setobj(obj1,obj2) \ + { const ktap_value *io2=(obj2); ktap_value *io1=(obj1); \ + io1->val = io2->val; io1->type = io2->type; } + +#define rawequalobj(t1, t2) \ + (ttisequal(t1, t2) && kp_equalobjv(NULL, t1, t2)) + +#define equalobj(ks, t1, t2) rawequalobj(t1, t2) + +#define incr_top(ks) {ks->top++;} + +#define NUMADD(a, b) ((a) + (b)) +#define NUMSUB(a, b) ((a) - (b)) +#define NUMMUL(a, b) ((a) * (b)) +#define NUMDIV(a, b) ((a) / (b)) +#define NUMUNM(a) (-(a)) +#define NUMEQ(a, b) ((a) == (b)) +#define NUMLT(a, b) ((a) < (b)) +#define NUMLE(a, b) ((a) <= (b)) +#define NUMISNAN(a) (!NUMEQ((a), (a))) + +/* todo: floor and pow in kernel */ +#define NUMMOD(a, b) ((a) % (b)) +#define NUMPOW(a, b) (pow(a, b)) + + +ktap_string *kp_tstring_newlstr(ktap_state *ks, const char *str, size_t l); +ktap_string *kp_tstring_newlstr_local(ktap_state *ks, const char *str, size_t l); +ktap_string *kp_tstring_new(ktap_state *ks, const char *str); +ktap_string *kp_tstring_new_local(ktap_state *ks, const char *str); +int kp_tstring_eqstr(ktap_string *a, ktap_string *b); +unsigned int kp_string_hash(const char *str, size_t l, unsigned int seed); +int kp_tstring_eqlngstr(ktap_string *a, ktap_string *b); +int kp_tstring_cmp(const ktap_string *ls, const ktap_string *rs); +void kp_tstring_resize(ktap_state *ks, int newsize); +void kp_tstring_freeall(ktap_state *ks); + +ktap_value *kp_table_set(ktap_state *ks, ktap_table *t, const ktap_value *key); +ktap_table *kp_table_new(ktap_state *ks); +const ktap_value *kp_table_getint(ktap_table *t, int key); +void kp_table_setint(ktap_state *ks, ktap_table *t, int key, ktap_value *v); +const ktap_value *kp_table_get(ktap_table *t, const ktap_value *key); +void kp_table_setvalue(ktap_state *ks, ktap_table *t, const ktap_value *key, ktap_value *val); +void kp_table_resize(ktap_state *ks, ktap_table *t, int nasize, int nhsize); +void kp_table_resizearray(ktap_state *ks, ktap_table *t, int nasize); +void kp_table_free(ktap_state *ks, ktap_table *t); +int kp_table_length(ktap_state *ks, ktap_table *t); +void kp_table_dump(ktap_state *ks, ktap_table *t); +void kp_table_clear(ktap_state *ks, ktap_table *t); +void kp_table_histogram(ktap_state *ks, ktap_table *t); +int kp_table_next(ktap_state *ks, ktap_table *t, StkId key); +void kp_table_atomic_inc(ktap_state *ks, ktap_table *t, ktap_value *key, int n); +void kp_aggraccval_dump(ktap_state *ks, ktap_aggraccval *acc); +ktap_aggrtable *kp_aggrtable_new(ktap_state *ks); +ktap_table *kp_aggrtable_synthesis(ktap_state *ks, ktap_aggrtable *ah); +void kp_aggrtable_dump(ktap_state *ks, ktap_aggrtable *ah); +void kp_aggrtable_free(ktap_state *ks, ktap_aggrtable *ah); +void kp_aggrtable_set(ktap_state *ks, ktap_aggrtable *ah, + ktap_value *key, ktap_value *val); +void kp_aggrtable_get(ktap_state *ks, ktap_aggrtable *ah, + ktap_value *key, ktap_value *val); +void kp_aggrtable_histogram(ktap_state *ks, ktap_aggrtable *ah); +void kp_obj_dump(ktap_state *ks, const ktap_value *v); +void kp_showobj(ktap_state *ks, const ktap_value *v); +int kp_objlen(ktap_state *ks, const ktap_value *rb); +void kp_objclone(ktap_state *ks, const ktap_value *o, ktap_value *newo, + ktap_gcobject **list); +ktap_gcobject *kp_newobject(ktap_state *ks, int type, size_t size, ktap_gcobject **list); +int kp_equalobjv(ktap_state *ks, const ktap_value *t1, const ktap_value *t2); +ktap_closure *kp_newlclosure(ktap_state *ks, int n); +ktap_proto *kp_newproto(ktap_state *ks); +ktap_upval *kp_newupval(ktap_state *ks); +void kp_free_gclist(ktap_state *ks, ktap_gcobject *o); +void kp_free_all_gcobject(ktap_state *ks); +void kp_header(u8 *h); + +int kp_str2d(const char *s, size_t len, ktap_number *result); + +#define kp_realloc(ks, v, osize, nsize, t) \ + ((v) = (t *)kp_reallocv(ks, v, osize * sizeof(t), nsize * sizeof(t))) + +#define kp_error(ks, args...) \ + do { \ + kp_printf(ks, "error: "args); \ + G(ks)->error = 1; \ + kp_exit(ks); \ + } while(0) + +#ifdef __KERNEL__ +#define G(ks) (ks->g) + +void *kp_malloc(ktap_state *ks, int size); +void kp_free(ktap_state *ks, void *addr); +void *kp_reallocv(ktap_state *ks, void *addr, int oldsize, int newsize); +void *kp_zalloc(ktap_state *ks, int size); + +void kp_printf(ktap_state *ks, const char *fmt, ...); +extern void __kp_puts(ktap_state *ks, const char *str); +extern void __kp_bputs(ktap_state *ks, const char *str); + +#define kp_puts(ks, str) ({ \ + static const char *trace_printk_fmt \ + __attribute__((section("__trace_printk_fmt"))) = \ + __builtin_constant_p(str) ? str : NULL; \ + \ + if (__builtin_constant_p(str)) \ + __kp_bputs(ks, trace_printk_fmt); \ + else \ + __kp_puts(ks, str); \ +}) + +#else +/* + * this is used for ktapc tstring operation, tstring need G(ks)->strt + * and G(ks)->seed, so ktapc need to init those field + */ +#define G(ks) (&dummy_global_state) +extern ktap_global_state dummy_global_state; + +#define kp_malloc(ks, size) malloc(size) +#define kp_free(ks, block) free(block) +#define kp_reallocv(ks, block, osize, nsize) realloc(block, nsize) +#define kp_printf(ks, args...) printf(args) +#define kp_puts(ks, str) printf("%s", str) +#define kp_exit(ks) exit(EXIT_FAILURE) +#endif + +#define __maybe_unused __attribute__((unused)) + +/* + * KTAP_QL describes how error messages quote program elements. + * CHANGE it if you want a different appearance. + */ +#define KTAP_QL(x) "'" x "'" +#define KTAP_QS KTAP_QL("%s") + +#endif /* __KTAP_TYPES_H__ */ + diff --git a/drivers/staging/ktap/interpreter/ktap.c b/drivers/staging/ktap/interpreter/ktap.c new file mode 100644 index 000000000000..18d8fc8ec63d --- /dev/null +++ b/drivers/staging/ktap/interpreter/ktap.c @@ -0,0 +1,235 @@ +/* + * ktap.c - ktapvm kernel module main entry + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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. + */ + +/* + * this file is the first file to be compile, add CONFIG_ checking in here. + * See Requirements in doc/introduction.txt + */ + +#include <linux/version.h> +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) +#error "Currently ktap don't support kernel older than 3.1" +#endif + +#if !CONFIG_EVENT_TRACING +#error "Please enable CONFIG_EVENT_TRACING before compile ktap" +#endif + +#if !CONFIG_PERF_EVENTS +#error "Please enable CONFIG_PERF_EVENTS before compile ktap" +#endif + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/file.h> +#include <linux/fcntl.h> +#include <linux/sched.h> +#include <linux/poll.h> +#include <linux/anon_inodes.h> +#include <linux/debugfs.h> +#include <linux/vmalloc.h> +#include "../include/ktap.h" + +static int load_trunk(struct ktap_parm *parm, unsigned long **buff) +{ + int ret; + unsigned long *vmstart; + + vmstart = vmalloc(parm->trunk_len); + if (!vmstart) + return -ENOMEM; + + ret = copy_from_user(vmstart, (void __user *)parm->trunk, + parm->trunk_len); + if (ret < 0) { + vfree(vmstart); + return -EFAULT; + } + + *buff = vmstart; + return 0; +} + +int gettimeofday_us(void) +{ + struct timeval tv; + + do_gettimeofday(&tv); + return tv.tv_sec * USEC_PER_SEC + tv.tv_usec; +} + +struct dentry *kp_dir_dentry; +static atomic_t kp_is_running = ATOMIC_INIT(0); + +/* Ktap Main Entry */ +static int ktap_main(struct file *file, ktap_parm *parm) +{ + unsigned long *buff = NULL; + ktap_state *ks; + ktap_closure *cl; + int start_time, delta_time; + int ret; + + if (atomic_inc_return(&kp_is_running) != 1) { + atomic_dec(&kp_is_running); + pr_info("only one ktap thread allow to run\n"); + return -EBUSY; + } + + start_time = gettimeofday_us(); + + ks = kp_newstate(parm, kp_dir_dentry); + if (unlikely(!ks)) { + ret = -ENOEXEC; + goto out; + } + + file->private_data = ks; + + ret = load_trunk(parm, &buff); + if (ret) { + pr_err("cannot load file\n"); + goto out; + } + + cl = kp_load(ks, (unsigned char *)buff); + + vfree(buff); + + if (cl) { + /* optimize bytecode before excuting */ + kp_optimize_code(ks, 0, cl->l.p); + + delta_time = gettimeofday_us() - start_time; + kp_verbose_printf(ks, "booting time: %d (us)\n", delta_time); + kp_call(ks, ks->top - 1, 0); + } + + kp_final_exit(ks); + + out: + atomic_dec(&kp_is_running); + return ret; +} + + +static void print_version(void) +{ +} + +static long ktap_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + ktap_parm parm; + int ret; + + switch (cmd) { + case KTAP_CMD_IOC_VERSION: + print_version(); + return 0; + case KTAP_CMD_IOC_RUN: + ret = copy_from_user(&parm, (void __user *)arg, + sizeof(ktap_parm)); + if (ret < 0) + return -EFAULT; + + return ktap_main(file, &parm); + default: + return -EINVAL; + }; + + return 0; +} + +static const struct file_operations ktap_fops = { + .llseek = no_llseek, + .unlocked_ioctl = ktap_ioctl, +}; + +static long ktapvm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int new_fd, err; + struct file *new_file; + + new_fd = get_unused_fd(); + if (new_fd < 0) + return new_fd; + + new_file = anon_inode_getfile("[ktap]", &ktap_fops, NULL, O_RDWR); + if (IS_ERR(new_file)) { + err = PTR_ERR(new_file); + put_unused_fd(new_fd); + return err; + } + + file->private_data = NULL; + fd_install(new_fd, new_file); + return new_fd; +} + +static const struct file_operations ktapvm_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = ktapvm_ioctl, +}; + +unsigned int kp_stub_exit_instr; + +static int __init init_ktap(void) +{ + struct dentry *ktapvm_dentry; + + kp_dir_dentry = debugfs_create_dir("ktap", NULL); + if (!kp_dir_dentry) { + pr_err("ktap: debugfs_create_dir failed\n"); + return -1; + } + + ktapvm_dentry = debugfs_create_file("ktapvm", 0444, kp_dir_dentry, NULL, + &ktapvm_fops); + + if (!ktapvm_dentry) { + pr_err("ktapvm: cannot create ktapvm file\n"); + debugfs_remove_recursive(kp_dir_dentry); + return -1; + } + + SET_OPCODE(kp_stub_exit_instr, OP_EXIT); + + return 0; +} + +static void __exit exit_ktap(void) +{ + debugfs_remove_recursive(kp_dir_dentry); +} + +module_init(init_ktap); +module_exit(exit_ktap); + +MODULE_AUTHOR("Jovi Zhangwei <[email protected]>"); +MODULE_DESCRIPTION("ktap"); +MODULE_LICENSE("GPL"); + +int kp_max_exec_count = 10000; +module_param_named(max_exec_count, kp_max_exec_count, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(max_exec_count, "non-mainthread max instruction execution count"); + diff --git a/drivers/staging/ktap/interpreter/library/ansilib.c b/drivers/staging/ktap/interpreter/library/ansilib.c new file mode 100644 index 000000000000..d058373e5f30 --- /dev/null +++ b/drivers/staging/ktap/interpreter/library/ansilib.c @@ -0,0 +1,153 @@ +/* + * ansilib.c - ANSI escape sequences library + * + * http://en.wikipedia.org/wiki/ANSI_escape_code + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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/ktap.h" + +/** + * function ansi.clear_screen - Move cursor to top left and clear screen. + * + * Description: Sends ansi code for moving cursor to top left and then the + * ansi code for clearing the screen from the cursor position to the end. + */ + +static int ktap_lib_clear_screen(ktap_state *ks) +{ + kp_printf(ks, "\033[1;1H\033[J"); + return 0; +} + +/** + * function ansi.set_color - Set the ansi Select Graphic Rendition mode. + * @fg: Foreground color to set. + * + * Description: Sends ansi code for Select Graphic Rendition mode for the + * given forground color. Black (30), Blue (34), Green (32), Cyan (36), + * Red (31), Purple (35), Brown (33), Light Gray (37). + */ + +static int ktap_lib_set_color(ktap_state *ks) +{ + int fg; + + kp_arg_check(ks, 1, KTAP_TNUMBER); + + fg = nvalue(kp_arg(ks, 1)); + kp_printf(ks, "\033[%dm", fg); + return 0; +} + +/** + * function ansi.set_color2 - Set the ansi Select Graphic Rendition mode. + * @fg: Foreground color to set. + * @bg: Background color to set. + * + * Description: Sends ansi code for Select Graphic Rendition mode for the + * given forground color, Black (30), Blue (34), Green (32), Cyan (36), + * Red (31), Purple (35), Brown (33), Light Gray (37) and the given + * background color, Black (40), Red (41), Green (42), Yellow (43), + * Blue (44), Magenta (45), Cyan (46), White (47). + */ +static int ktap_lib_set_color2(ktap_state *ks) +{ + int fg, bg; + + kp_arg_check(ks, 1, KTAP_TNUMBER); + kp_arg_check(ks, 2, KTAP_TNUMBER); + + fg = nvalue(kp_arg(ks, 1)); + bg = nvalue(kp_arg(ks, 2)); + kp_printf(ks, "\033[%d;%dm", fg, bg); + return 0; +} + +/** + * function ansi.set_color3 - Set the ansi Select Graphic Rendition mode. + * @fg: Foreground color to set. + * @bg: Background color to set. + * @attr: Color attribute to set. + * + * Description: Sends ansi code for Select Graphic Rendition mode for the + * given forground color, Black (30), Blue (34), Green (32), Cyan (36), + * Red (31), Purple (35), Brown (33), Light Gray (37), the given + * background color, Black (40), Red (41), Green (42), Yellow (43), + * Blue (44), Magenta (45), Cyan (46), White (47) and the color attribute + * All attributes off (0), Intensity Bold (1), Underline Single (4), + * Blink Slow (5), Blink Rapid (6), Image Negative (7). + */ +static int ktap_lib_set_color3(ktap_state *ks) +{ + int fg, bg, attr; + + kp_arg_check(ks, 1, KTAP_TNUMBER); + kp_arg_check(ks, 2, KTAP_TNUMBER); + kp_arg_check(ks, 3, KTAP_TNUMBER); + + fg = nvalue(kp_arg(ks, 1)); + bg = nvalue(kp_arg(ks, 2)); + attr = nvalue(kp_arg(ks, 3)); + + if (attr) + kp_printf(ks, "\033[%d;%d;%dm", fg, bg, attr); + else + kp_printf(ks, "\033[%d;%dm", fg, bg); + + return 0; +} + +/** + * function ansi.reset_color - Resets Select Graphic Rendition mode. + * + * Description: Sends ansi code to reset foreground, background and color + * attribute to default values. + */ +static int ktap_lib_reset_color(ktap_state *ks) +{ + kp_printf(ks, "\033[0;0m"); + return 0; +} + +/** + * function ansi.new_line - Move cursor to new line. + * + * Description: Sends ansi code new line. + */ +static int ktap_lib_new_line (ktap_state *ks) +{ + kp_printf(ks, "\12"); + return 0; +} + +static const ktap_Reg ansi_funcs[] = { + {"clear_screen", ktap_lib_clear_screen}, + {"set_color", ktap_lib_set_color}, + {"set_color2", ktap_lib_set_color2}, + {"set_color3", ktap_lib_set_color3}, + {"reset_color", ktap_lib_reset_color}, + {"new_line", ktap_lib_new_line}, + {NULL} +}; + +void kp_init_ansilib(ktap_state *ks) +{ + kp_register_lib(ks, "ansi", ansi_funcs); +} diff --git a/drivers/staging/ktap/interpreter/library/baselib.c b/drivers/staging/ktap/interpreter/library/baselib.c new file mode 100644 index 000000000000..4bcdc620f9d9 --- /dev/null +++ b/drivers/staging/ktap/interpreter/library/baselib.c @@ -0,0 +1,455 @@ +/* + * baselib.c - ktapvm kernel module base library + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <linux/hardirq.h> +#include <linux/kallsyms.h> +#include <linux/sched.h> +#include <linux/uaccess.h> +#include <linux/utsname.h> +#include <linux/time.h> +#include <linux/clocksource.h> +#include <linux/ring_buffer.h> +#include <linux/stacktrace.h> +#include "../../include/ktap.h" + +static int ktap_lib_next(ktap_state *ks) +{ + ktap_table *t = hvalue(ks->top - 2); + + if (kp_table_next(ks, t, ks->top-1)) { + ks->top += 1; + return 2; + } else { + ks->top -= 1; + setnilvalue(ks->top++); + return 1; + } +} + +static int ktap_lib_pairs(ktap_state *ks) +{ + ktap_value *v = kp_arg(ks, 1); + ktap_table *t; + + if (G(ks)->mainthread != ks) { + kp_error(ks, "only mainthread can call table pairs\n"); + return -1; + } + + if (ttistable(v)) { + t = hvalue(v); + } else if (ttisaggrtable(v)) { + t = kp_aggrtable_synthesis(ks, ahvalue(v)); + } else if (isnil(v)) { + kp_error(ks, "table is nil in pairs\n"); + return 0; + } else { + kp_error(ks, "wrong argument for pairs\n"); + return 0; + } + + setfvalue(ks->top++, ktap_lib_next); + sethvalue(ks->top++, t); + setnilvalue(ks->top++); + return 3; +} + +static int ktap_lib_len(ktap_state *ks) +{ + int len = kp_objlen(ks, kp_arg(ks, 1)); + + if (len < 0) + return -1; + + setnvalue(ks->top, len); + incr_top(ks); + return 1; +} + +static int ktap_lib_print(ktap_state *ks) +{ + int i; + int n = kp_arg_nr(ks); + + for (i = 1; i <= n; i++) { + ktap_value *arg = kp_arg(ks, i); + if (i > 1) + kp_puts(ks, "\t"); + kp_showobj(ks, arg); + } + + kp_puts(ks, "\n"); + + return 0; +} + +/* don't engage with tstring when printf, use buffer directly */ +static int ktap_lib_printf(ktap_state *ks) +{ + struct trace_seq *seq; + + preempt_disable_notrace(); + + seq = kp_percpu_data(KTAP_PERCPU_DATA_BUFFER); + trace_seq_init(seq); + + if (kp_strfmt(ks, seq)) + return 0; + + seq->buffer[seq->len] = '\0'; + kp_transport_write(ks, seq->buffer, seq->len + 1); + + preempt_enable_notrace(); + return 0; +} + +#ifdef CONFIG_STACKTRACE +static int ktap_lib_print_backtrace(ktap_state *ks) +{ + kp_transport_print_backtrace(ks); + return 0; +} +#else +static int ktap_lib_print_backtrace(ktap_state *ks) +{ + kp_error(ks, "Please enable CONFIG_STACKTRACE before use " + "ktap print_backtrace\n"); + return 0; +} +#endif + +static int ktap_lib_backtrace(ktap_state *ks) +{ + struct stack_trace trace; + ktap_btrace *bt; + + bt = kp_percpu_data(KTAP_PERCPU_DATA_BTRACE); + + trace.nr_entries = 0; + trace.skip = 10; + trace.max_entries = KTAP_STACK_MAX_ENTRIES; + trace.entries = &bt->entries[0]; + save_stack_trace(&trace); + + bt->nr_entries = trace.nr_entries; + setbtvalue(ks->top, bt); + incr_top(ks); + return 1; +} + +extern unsigned long long ns2usecs(cycle_t nsec); +static int ktap_lib_print_trace_clock(ktap_state *ks) +{ + unsigned long long t; + unsigned long secs, usec_rem; + u64 timestamp; + + /* use ring buffer's timestamp */ + timestamp = ring_buffer_time_stamp(G(ks)->buffer, smp_processor_id()); + + t = ns2usecs(timestamp); + usec_rem = do_div(t, USEC_PER_SEC); + secs = (unsigned long)t; + + kp_printf(ks, "%5lu.%06lu\n", secs, usec_rem); + + return 0; +} + +static int ktap_lib_exit(ktap_state *ks) +{ + kp_exit(ks); + + /* do not execute bytecode any more in this thread */ + return -1; +} + +static int ktap_lib_pid(ktap_state *ks) +{ + pid_t pid = task_tgid_vnr(current); + + setnvalue(ks->top, (int)pid); + incr_top(ks); + return 1; +} + +static int ktap_lib_tid(ktap_state *ks) +{ + pid_t pid = task_pid_vnr(current); + + setnvalue(ks->top, (int)pid); + incr_top(ks); + return 1; +} + +static int ktap_lib_execname(ktap_state *ks) +{ + ktap_string *ts = kp_tstring_new(ks, current->comm); + setsvalue(ks->top, ts); + incr_top(ks); + return 1; +} + +static int ktap_lib_cpu(ktap_state *ks) +{ + setnvalue(ks->top, smp_processor_id()); + incr_top(ks); + return 1; +} + +static int ktap_lib_num_cpus(ktap_state *ks) +{ + setnvalue(ks->top, num_online_cpus()); + incr_top(ks); + return 1; +} + +static int ktap_lib_in_interrupt(ktap_state *ks) +{ + int ret = in_interrupt(); + + setnvalue(ks->top, ret); + incr_top(ks); + return 1; +} + +static int ktap_lib_arch(ktap_state *ks) +{ + setsvalue(ks->top, kp_tstring_new(ks, utsname()->machine)); + incr_top(ks); + return 1; +} + +static int ktap_lib_kernel_v(ktap_state *ks) +{ + setsvalue(ks->top, kp_tstring_new(ks, utsname()->release)); + incr_top(ks); + return 1; +} + +static int ktap_lib_user_string(ktap_state *ks) +{ + unsigned long addr; + char str[256] = {0}; + int ret; + + kp_arg_check(ks, 1, KTAP_TNUMBER); + + addr = nvalue(kp_arg(ks, 1)); + + pagefault_disable(); + ret = __copy_from_user_inatomic((void *)str, (const void *)addr, 256); + (void) &ret; /* Silence compiler warning. */ + pagefault_enable(); + str[255] = '\0'; + setsvalue(ks->top, kp_tstring_new(ks, str)); + + incr_top(ks); + return 1; +} + +static int ktap_lib_histogram(ktap_state *ks) +{ + ktap_value *v = kp_arg(ks, 1); + + if (G(ks)->mainthread != ks) { + kp_error(ks, "only mainthread can call table historgram\n"); + return -1; + } + + if (ttistable(v)) + kp_table_histogram(ks, hvalue(v)); + else if (ttisaggrtable(v)) + kp_aggrtable_histogram(ks, ahvalue(v)); + + return 0; +} + +static int ktap_lib_aggr_table(ktap_state *ks) +{ + ktap_aggrtable *ah; + + ah = kp_aggrtable_new(ks); + setahvalue(ks->top, ah); + incr_top(ks); + return 1; +} + +static int ktap_lib_aggr_count(ktap_state *ks) +{ + setaggrvalue(ks->top, AGGREGATION_TYPE_COUNT); + incr_top(ks); + return 1; +} + +static int ktap_lib_aggr_max(ktap_state *ks) +{ + kp_arg_check(ks, 1, KTAP_TNUMBER); + + ks->aggr_accval = nvalue(kp_arg(ks, 1)); + setaggrvalue(ks->top, AGGREGATION_TYPE_MAX); + incr_top(ks); + return 1; +} + +static int ktap_lib_aggr_min(ktap_state *ks) +{ + kp_arg_check(ks, 1, KTAP_TNUMBER); + + ks->aggr_accval = nvalue(kp_arg(ks, 1)); + setaggrvalue(ks->top, AGGREGATION_TYPE_MIN); + incr_top(ks); + return 1; +} + +static int ktap_lib_aggr_sum(ktap_state *ks) +{ + kp_arg_check(ks, 1, KTAP_TNUMBER); + + ks->aggr_accval = nvalue(kp_arg(ks, 1)); + setaggrvalue(ks->top, AGGREGATION_TYPE_SUM); + incr_top(ks); + return 1; +} + +static int ktap_lib_aggr_avg(ktap_state *ks) +{ + kp_arg_check(ks, 1, KTAP_TNUMBER); + + ks->aggr_accval = nvalue(kp_arg(ks, 1)); + setaggrvalue(ks->top, AGGREGATION_TYPE_AVG); + incr_top(ks); + return 1; +} + +static int ktap_lib_delete(ktap_state *ks) +{ + kp_arg_check(ks, 1, KTAP_TTABLE); + + kp_table_clear(ks, hvalue(kp_arg(ks, 1))); + return 0; +} + +static int ktap_lib_gettimeofday_us(ktap_state *ks) +{ + setnvalue(ks->top, gettimeofday_us()); + incr_top(ks); + + return 1; +} + +/* + * use gdb to get field offset of struct task_struct, for example: + * + * gdb vmlinux + * (gdb)p &(((struct task_struct *)0).prio) + */ +static int ktap_lib_curr_task_info(ktap_state *ks) +{ + int offset; + int fetch_bytes; + + kp_arg_check(ks, 1, KTAP_TNUMBER); + + offset = nvalue(kp_arg(ks, 1)); + + if (kp_arg_nr(ks) == 1) + fetch_bytes = 4; /* default fetch 4 bytes*/ + else { + kp_arg_check(ks, 2, KTAP_TNUMBER); + fetch_bytes = nvalue(kp_arg(ks, 2)); + } + + if (offset >= sizeof(struct task_struct)) { + setnilvalue(ks->top++); + kp_error(ks, "access out of bound value of task_struct\n"); + return 1; + } + +#define RET_VALUE ((unsigned long)current + offset) + + switch (fetch_bytes) { + case 4: + setnvalue(ks->top, *(unsigned int *)RET_VALUE); + break; + case 8: + setnvalue(ks->top, *(unsigned long *)RET_VALUE); + break; + default: + kp_error(ks, "unsupported fetch bytes in curr_task_info\n"); + setnilvalue(ks->top); + break; + } + +#undef RET_VALUE + + incr_top(ks); + return 1; +} + +/* + * This built-in function mainly purpose scripts/schedule/schedtimes.kp + */ +static int ktap_lib_in_iowait(ktap_state *ks) +{ + setnvalue(ks->top, current->in_iowait); + incr_top(ks); + + return 1; +} + +static const ktap_Reg base_funcs[] = { + {"pairs", ktap_lib_pairs}, + {"len", ktap_lib_len}, + {"print", ktap_lib_print}, + {"printf", ktap_lib_printf}, + {"print_backtrace", ktap_lib_print_backtrace}, + {"backtrace", ktap_lib_backtrace}, + {"print_trace_clock", ktap_lib_print_trace_clock}, + {"in_interrupt", ktap_lib_in_interrupt}, + {"exit", ktap_lib_exit}, + {"pid", ktap_lib_pid}, + {"tid", ktap_lib_tid}, + {"execname", ktap_lib_execname}, + {"cpu", ktap_lib_cpu}, + {"num_cpus", ktap_lib_num_cpus}, + {"arch", ktap_lib_arch}, + {"kernel_v", ktap_lib_kernel_v}, + {"user_string", ktap_lib_user_string}, + {"histogram", ktap_lib_histogram}, + {"aggr_table", ktap_lib_aggr_table}, + {"count", ktap_lib_aggr_count}, + {"max", ktap_lib_aggr_max}, + {"min", ktap_lib_aggr_min}, + {"sum", ktap_lib_aggr_sum}, + {"avg", ktap_lib_aggr_avg}, + + {"delete", ktap_lib_delete}, + {"gettimeofday_us", ktap_lib_gettimeofday_us}, + {"curr_taskinfo", ktap_lib_curr_task_info}, + {"in_iowait", ktap_lib_in_iowait}, + {NULL} +}; + +void kp_init_baselib(ktap_state *ks) +{ + kp_register_lib(ks, NULL, base_funcs); +} diff --git a/drivers/staging/ktap/interpreter/library/kdebug.c b/drivers/staging/ktap/interpreter/library/kdebug.c new file mode 100644 index 000000000000..a9477beeaebf --- /dev/null +++ b/drivers/staging/ktap/interpreter/library/kdebug.c @@ -0,0 +1,449 @@ +/* + * kdebug.c - ktap probing core implementation + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <linux/module.h> +#include <linux/ctype.h> +#include <linux/version.h> +#include <linux/ftrace_event.h> +#include "../../include/ktap.h" + +static void ktap_call_probe_closure(ktap_state *mainthread, ktap_closure *cl, + struct ktap_event *e) +{ + ktap_state *ks; + ktap_value *func; + + ks = kp_newthread(mainthread); + setcllvalue(ks->top, cl); + func = ks->top; + incr_top(ks); + + ks->current_event = e; + + kp_call(ks, func, 0); + + ks->current_event = NULL; + kp_exitthread(ks); +} + +void kp_event_tostring(ktap_state *ks, struct trace_seq *seq) +{ + struct ktap_event *e = ks->current_event; + struct trace_iterator *iter; + struct trace_event *ev; + enum print_line_t ret = TRACE_TYPE_NO_CONSUME; + + /* Simulate the iterator */ + + /* + * use temp percpu buffer as trace_iterator + * we cannot use same temp buffer as printf. + */ + iter = kp_percpu_data(KTAP_PERCPU_DATA_BUFFER2); + + trace_seq_init(&iter->seq); + iter->ent = e->entry; + + ev = &(e->call->event); + if (ev) + ret = ev->funcs->trace(iter, 0, ev); + + if (ret != TRACE_TYPE_NO_CONSUME) { + struct trace_seq *s = &iter->seq; + int len = s->len >= PAGE_SIZE ? PAGE_SIZE - 1 : s->len; + + s->buffer[len] = '\0'; + trace_seq_puts(seq, s->buffer); + } +} + +#if 0 +/* check pt_regs defintion in linux/arch/x86/include/asm/ptrace.h */ +/* support other architecture pt_regs showing */ +static void event_regstr(ktap_state *ks, struct ktap_event *e, StkId ra) +{ + struct pt_regs *regs = e->regs; + char str[256] = {0}; + +#if defined(CONFIG_X86_32) + snprintf(str, sizeof(str), + "{ax: 0x%lx, orig_ax: 0x%lx, bx: 0x%lx, cx: 0x%lx, dx: 0x%lx, " + "si: 0x%lx, di: 0x%lx, bp: 0x%lx, ds: 0x%lx, es: 0x%lx, fs: 0x%lx, " + "gs: 0x%lx, ip: 0x%lx, cs: 0x%lx, flags: 0x%lx, sp: 0x%lx, ss: 0x%lx}\n", + regs->ax, regs->orig_ax, regs->bx, regs->cx, regs->dx, + regs->si, regs->di, regs->bp, regs->ds, regs->es, regs->fs, + regs->gs, regs->ip, regs->cs, regs->flags, regs->sp, regs->ss); +#elif defined(CONFIG_X86_64) + /* x86_64 pt_regs doesn't have ds, es, fs or gs. */ + snprintf(str, sizeof(str), + "{ax: 0x%lx, orig_ax: 0x%lx, bx: 0x%lx, cx: 0x%lx, dx: 0x%lx, " + "si: 0x%lx, di: 0x%lx, r8: 0x%lx, r9: 0x%lx, r10: 0x%lx, r11: 0x%lx, " + "r12: 0x%lx, r13: 0x%lx, r14: 0x%lx, r15: 0x%lx, bp: 0x%lx, ip: 0x%lx, " + "cs: 0x%lx, flags: 0x%lx, sp: 0x%lx, ss: 0x%lx}\n", + regs->ax, regs->orig_ax, regs->bx, regs->cx, regs->dx, + regs->si, regs->di, regs->r8, regs->r9, regs->r10, regs->r11, + regs->r12, regs->r13, regs->r14, regs->r15, regs->bp, regs->ip, + regs->cs, regs->flags, regs->sp, regs->ss); +#endif + setsvalue(ra, kp_tstring_new_local(ks, str)); +} +#endif + +/***************************/ +/* This definition should keep update with kernel/trace/trace.h */ +struct ftrace_event_field { + struct list_head link; + const char *name; + const char *type; + int filter_type; + int offset; + int size; + int is_signed; +}; + +static struct list_head *ktap_get_fields(struct ftrace_event_call *event_call) +{ + if (!event_call->class->get_fields) + return &event_call->class->fields; + return event_call->class->get_fields(event_call); +} + +static void get_field_value(ktap_state *ks, struct ktap_event *e, + struct ftrace_event_field *field, ktap_value *ra) +{ + void *value = (unsigned char *)e->entry + field->offset; + + if (field->size == 4) { + int n = *(int *)value; + setnvalue(ra, n); + return; + } else if (field->size == 8) { + long n = *(long *)value; + setnvalue(ra, n); + return; + } + + if (!strncmp(field->type, "char", 4)) { + setsvalue(ra, kp_tstring_new(ks, (char *)value)); + return; + } +} + +void kp_event_getarg(ktap_state *ks, ktap_value *ra, int n) +{ + struct ktap_event *e = ks->current_event; + int index = n; + struct ftrace_event_field *field; + struct list_head *head; + + /* this is very slow and not safe, fix it in future */ + head = ktap_get_fields(e->call); + list_for_each_entry_reverse(field, head, link) { + if (--index == 0) { + get_field_value(ks, e, field, ra); + return; + } + } + + setnilvalue(ra); + return; +} + +/* Callback function for perf event subsystem + * make ktap reentrant, don't disable irq in callback function, + * same as perf and ftrace. to make reentrant, we need some + * percpu data to be context isolation(irq/sirq/nmi/process) + * + * perf callback already consider on the recursion issue, + * so ktap don't need to check again in here. + * + * Note tracepoint handler is calling with rcu_read_lock. + */ +static void ktap_overflow_callback(struct perf_event *event, + struct perf_sample_data *data, + struct pt_regs *regs) +{ + struct ktap_probe_event *ktap_pevent; + struct ktap_event e; + ktap_state *ks; + int rctx; + + ktap_pevent = event->overflow_handler_context; + ks = ktap_pevent->ks; + + if (unlikely(ks->stop)) + return; + + rctx = get_recursion_context(); + if (rctx < 0) + return; + + /* profile perf event don't have valid associated tp_event */ + if (event->tp_event) { + e.call = event->tp_event; + e.entry = data->raw->data; + e.entry_size = data->raw->size; + } + e.pevent = ktap_pevent; + e.regs = regs; + + ktap_call_probe_closure(ks, ktap_pevent->cl, &e); + + put_recursion_context(rctx); +} + +static void perf_destructor(struct ktap_probe_event *ktap_pevent) +{ + perf_event_release_kernel(ktap_pevent->perf); +} + +static int (*kp_ftrace_profile_set_filter)(struct perf_event *event, + int event_id, char *filter_str); + +/* + * Generic perf event register function + * used by tracepoints/kprobe/uprobe/profile-timer/hw_breakpoint. + */ +void kp_perf_event_register(ktap_state *ks, struct perf_event_attr *attr, + struct task_struct *task, char *filter, + ktap_closure *cl) +{ + struct ktap_probe_event *ktap_pevent; + struct perf_event *event; + int cpu, ret; + + kp_verbose_printf(ks, "enable perf event id: %d, filter: %s " + "pid: %d\n", attr->config, filter, + task ? task_tgid_vnr(task) : -1); + + /* + * don't tracing until ktap_wait, the reason is: + * 1). some event may hit before apply filter + * 2). more simple to manage tracing thread + * 3). avoid race with mainthread. + * + * Another way to do this is make attr.disabled as 1, then use + * perf_event_enable after filter apply, however, perf_event_enable + * was not exported in kernel older than 3.3, so we drop this method. + */ + ks->stop = 1; + + for_each_cpu(cpu, G(ks)->cpumask) { + ktap_pevent = kp_zalloc(ks, sizeof(*ktap_pevent)); + ktap_pevent->ks = ks; + ktap_pevent->cl = cl; + event = perf_event_create_kernel_counter(attr, cpu, task, + ktap_overflow_callback, + ktap_pevent); + if (IS_ERR(event)) { + int err = PTR_ERR(event); + kp_error(ks, "unable register perf event %d on cpu %d, " + "err: %d\n", attr->config, cpu, err); + kp_free(ks, ktap_pevent); + return; + } + + ktap_pevent->perf = event; + INIT_LIST_HEAD(&ktap_pevent->list); + list_add_tail(&ktap_pevent->list, &G(ks)->probe_events_head); + + if (!filter) + continue; + + ret = kp_ftrace_profile_set_filter(event, attr->config, filter); + if (ret) { + kp_error(ks, "unable set filter %s for event id %d, " + "ret: %d\n", filter, attr->config, ret); + perf_destructor(ktap_pevent); + list_del(&ktap_pevent->list); + kp_free(ks, ktap_pevent); + return; + } + } +} + +static void end_probes(struct ktap_state *ks) +{ + struct ktap_probe_event *ktap_pevent; + struct list_head *tmp, *pos; + struct list_head *head = &G(ks)->probe_events_head; + + list_for_each(pos, head) { + ktap_pevent = container_of(pos, struct ktap_probe_event, + list); + perf_destructor(ktap_pevent); + } + /* + * Ensure our callback won't be called anymore. The buffers + * will be freed after that. + */ + tracepoint_synchronize_unregister(); + + list_for_each_safe(pos, tmp, head) { + ktap_pevent = container_of(pos, struct ktap_probe_event, + list); + list_del(&ktap_pevent->list); + kp_free(ks, ktap_pevent); + } +} + +static int ktap_lib_probe_by_id(ktap_state *ks) +{ + const char *ids_str; + char *start; + ktap_closure *cl; + struct task_struct *task = G(ks)->trace_task; + char filter_str[128] = {0}; + char *filter, *ptr1, *sep, *ptr; + + kp_arg_check(ks, 1, KTAP_TSTRING); + kp_arg_check(ks, 2, KTAP_TFUNCTION); + + ids_str = svalue(kp_arg(ks, 1)); + cl = clvalue(kp_arg(ks, 2)); + + start = (char *)ids_str; + + again: + filter = NULL; + + sep = strchr(start, ','); + if (!sep) + ptr1 = strchr(start, '/'); + else + ptr1 = strnchr(start, sep - start, '/'); + + if (ptr1) { + char *ptr2 = strrchr(ptr1 + 1, '/'); + + if (ptr2) { + memset(filter_str, 0, sizeof(filter_str)); + strncpy(filter_str, ptr1 + 1, ptr2 - ptr1 - 1); + filter = &filter_str[0]; + } else { + kp_printf(ks, "cannot parse ids_str: %s\n", ids_str); + return -1; + } + } + + for (ptr = start; *ptr != ',' && *ptr != '\0' && *ptr != '/'; ptr++) { + char token[32] = {0}; + int id; + int i = 0; + + if (*ptr == ' ') + continue; + + while (isdigit(*ptr)) { + token[i++] = *ptr++; + } + + if (!kstrtoint(token, 10, &id)) { + struct perf_event_attr attr; + + memset(&attr, 0, sizeof(attr)); + attr.type = PERF_TYPE_TRACEPOINT; + attr.config = id; + attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | + PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD; + attr.sample_period = 1; + attr.size = sizeof(attr); + attr.disabled = 0; + + kp_perf_event_register(ks, &attr, task, filter, cl); + } + } + + if (sep && (*(sep + 1) != '\0')) { + start = sep + 1; + goto again; + } + + return 0; +} + +static int ktap_lib_probe_end(ktap_state *ks) +{ + kp_arg_check(ks, 1, KTAP_TFUNCTION); + + G(ks)->trace_end_closure = clvalue(kp_arg(ks, 1)); + return 0; +} + +static int ktap_lib_traceoff(ktap_state *ks) +{ + end_probes(ks); + + /* call trace_end_closure after probed end */ + if (G(ks)->trace_end_closure) { + setcllvalue(ks->top, G(ks)->trace_end_closure); + incr_top(ks); + kp_call(ks, ks->top - 1, 0); + G(ks)->trace_end_closure = NULL; + } + + return 0; +} + +void kp_probe_exit(ktap_state *ks) +{ + if (!G(ks)->trace_enabled) + return; + + end_probes(ks); + + /* call trace_end_closure after probed end */ + if (!G(ks)->error && G(ks)->trace_end_closure) { + setcllvalue(ks->top, G(ks)->trace_end_closure); + incr_top(ks); + kp_call(ks, ks->top - 1, 0); + G(ks)->trace_end_closure = NULL; + } + + G(ks)->trace_enabled = 0; +} + +int kp_probe_init(ktap_state *ks) +{ + G(ks)->trace_enabled = 1; + return 0; +} + +static const ktap_Reg kdebuglib_funcs[] = { + {"probe_by_id", ktap_lib_probe_by_id}, + {"probe_end", ktap_lib_probe_end}, + {"traceoff", ktap_lib_traceoff}, + {NULL} +}; + +void kp_init_kdebuglib(ktap_state *ks) +{ + kp_ftrace_profile_set_filter = + (void *)kallsyms_lookup_name("ftrace_profile_set_filter"); + if (!kp_ftrace_profile_set_filter) { + printk("ktap: cannot lookup ftrace_profile_set_filter " + "in kallsyms\n"); + return; + } + + kp_register_lib(ks, "kdebug", kdebuglib_funcs); +} + diff --git a/drivers/staging/ktap/interpreter/library/timer.c b/drivers/staging/ktap/interpreter/library/timer.c new file mode 100644 index 000000000000..759f917b3658 --- /dev/null +++ b/drivers/staging/ktap/interpreter/library/timer.c @@ -0,0 +1,192 @@ +/* + * timer.c - timer library support for ktap + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <linux/ctype.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/sched.h> +#include "../../include/ktap.h" + +struct hrtimer_ktap { + struct hrtimer timer; + ktap_state *ks; + ktap_closure *cl; + u64 ns; + struct list_head list; +}; + +/* + * Currently ktap disallow tracing event in timer callback closure, + * that will corrupt ktap_state and ktap stack, because timer closure + * and event closure use same irq percpu ktap_state and stack. + * We can use a different percpu ktap_state and stack for timer purpuse, + * but that's don't bring any big value with cost on memory consuming. + * + * So just simply disable tracing in timer closure, + * get_recursion_context()/put_recursion_context() is used for this purpose. + * + * option: export perf_swevent_put_recursion_context to slove this issue. + */ +static enum hrtimer_restart hrtimer_ktap_fn(struct hrtimer *timer) +{ + struct hrtimer_ktap *t; + ktap_state *ks; + int rctx; + + rcu_read_lock_sched_notrace(); + rctx = get_recursion_context(); + + t = container_of(timer, struct hrtimer_ktap, timer); + + ks = kp_newthread(t->ks); + setcllvalue(ks->top, t->cl); + incr_top(ks); + kp_call(ks, ks->top - 1, 0); + kp_exitthread(ks); + + hrtimer_add_expires_ns(timer, t->ns); + + put_recursion_context(rctx); + rcu_read_unlock_sched_notrace(); + + return HRTIMER_RESTART; +} + +static void set_tick_timer(ktap_state *ks, u64 period, ktap_closure *cl) +{ + struct hrtimer_ktap *t; + + t = kp_malloc(ks, sizeof(*t)); + t->ks = ks; + t->cl = cl; + t->ns = period; + + INIT_LIST_HEAD(&t->list); + list_add(&t->list, &(G(ks)->timers)); + + hrtimer_init(&t->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + t->timer.function = hrtimer_ktap_fn; + hrtimer_start(&t->timer, ns_to_ktime(period), HRTIMER_MODE_REL); +} + +static void set_profile_timer(ktap_state *ks, u64 period, ktap_closure *cl) +{ + struct perf_event_attr attr; + + memset(&attr, 0, sizeof(attr)); + attr.type = PERF_TYPE_SOFTWARE; + attr.config = PERF_COUNT_SW_CPU_CLOCK; + attr.sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | + PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD; + attr.sample_period = period; + attr.size = sizeof(attr); + attr.disabled = 0; + + kp_perf_event_register(ks, &attr, NULL, NULL, cl); +} + +static int do_tick_profile(ktap_state *ks, int is_tick) +{ + const char *str, *tmp; + char interval_str[32] = {0}; + char suffix[10] = {0}; + int n, i = 0; + int factor; + + kp_arg_check(ks, 1, KTAP_TSTRING); + kp_arg_check(ks, 2, KTAP_TFUNCTION); + + str = svalue(kp_arg(ks, 1)); + tmp = str; + while (isdigit(*tmp)) + tmp++; + + strncpy(interval_str, str, tmp - str); + if (kstrtoint(interval_str, 10, &n)) + goto error; + + strncpy(suffix, tmp, 9); + while (suffix[i] != ' ' && suffix[i] != '\0') + i++; + + suffix[i] = '\0'; + + if (!strcmp(suffix, "s") || !strcmp(suffix, "sec")) + factor = NSEC_PER_SEC; + else if (!strcmp(suffix, "ms") || !strcmp(suffix, "msec")) + factor = NSEC_PER_MSEC; + else if (!strcmp(suffix, "us") || !strcmp(suffix, "usec")) + factor = NSEC_PER_USEC; + else + goto error; + + if (is_tick) + set_tick_timer(ks, (u64)factor * n, clvalue(kp_arg(ks, 2))); + else + set_profile_timer(ks, (u64)factor * n, clvalue(kp_arg(ks, 2))); + + return 0; + + error: + kp_error(ks, "cannot parse timer interval: %s\n", str); + return -1; +} + +/* + * tick-n probes fire on only one CPU per interval. + * valid time suffixes: sec/s, msec/ms, usec/us + */ +static int ktap_lib_tick(ktap_state *ks) +{ + return do_tick_profile(ks, 1); +} + +/* + * A profile-n probe fires every fixed interval on every CPU + * valid time suffixes: sec/s, msec/ms, usec/us + */ +static int ktap_lib_profile(ktap_state *ks) +{ + return do_tick_profile(ks, 0); +} + +void kp_exit_timers(ktap_state *ks) +{ + struct hrtimer_ktap *t, *tmp; + struct list_head *timers_list = &(G(ks)->timers); + + list_for_each_entry_safe(t, tmp, timers_list, list) { + hrtimer_cancel(&t->timer); + kp_free(ks, t); + } +} + +static const ktap_Reg timerlib_funcs[] = { + {"profile", ktap_lib_profile}, + {"tick", ktap_lib_tick}, + {NULL} +}; + +void kp_init_timerlib(ktap_state *ks) +{ + kp_register_lib(ks, "timer", timerlib_funcs); +} + diff --git a/drivers/staging/ktap/interpreter/loader.c b/drivers/staging/ktap/interpreter/loader.c new file mode 100644 index 000000000000..0da54d7ef146 --- /dev/null +++ b/drivers/staging/ktap/interpreter/loader.c @@ -0,0 +1,310 @@ +/* + * loader.c - loader for ktap bytecode chunk file + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * Copyright (C) 1994-2013 Lua.org, PUC-Rio. + * - The part of code in this file is copied from lua initially. + * - lua's MIT license is compatible with GPL. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <linux/slab.h> +#include "../include/ktap.h" + +#define KTAPC_TAIL "\x19\x93\r\n\x1a\n" + +struct load_state { + unsigned char *buff; + int pos; + ktap_state *ks; +}; + +#define READ_CHAR(S) (S->buff[S->pos++]) +#define READ_BYTE(S) READ_CHAR(S) +#define READ_INT(S) load_int(S) +#define READ_NUMBER(S) load_number(S) +#define READ_STRING(S) load_string(S) +#define READ_VECTOR(S, dst, size) \ + do { \ + memcpy(dst, &S->buff[S->pos], size); \ + S->pos += size; \ + } while(0) + +#define NEW_VECTOR(S, size) kp_malloc(S->ks, size) +#define GET_CURRENT(S) &S->buff[S->pos] +#define ADD_POS(S, size) S->pos += size + + +static int load_function(struct load_state *S, ktap_proto *f); + + +static int load_int(struct load_state *S) +{ + int x; + + READ_VECTOR(S, &x, sizeof(int)); + return x; +} + +static int load_number(struct load_state *S) +{ + int x; + + READ_VECTOR(S, &x, sizeof(ktap_number)); + return x; +} + +static ktap_string *load_string(struct load_state *S) +{ + ktap_string *ts; + size_t size; + + size = READ_INT(S); + + if (!size) + return NULL; + else { + char *s = GET_CURRENT(S); + ADD_POS(S, size); + /* remove trailing '\0' */ + ts = kp_tstring_newlstr(S->ks, s, size - 1); + return ts; + } +} + + +static int load_code(struct load_state *S, ktap_proto *f) +{ + int n = READ_INT(S); + + f->sizecode = n; + f->code = NEW_VECTOR(S, n * sizeof(ktap_instruction)); + READ_VECTOR(S, f->code, n * sizeof(ktap_instruction)); + + return 0; +} + +static int load_constants(struct load_state *S, ktap_proto *f) +{ + int i,n; + + n = READ_INT(S); + + f->sizek = n; + f->k = NEW_VECTOR(S, n * sizeof(ktap_value)); + for (i = 0; i < n; i++) + setnilvalue(&f->k[i]); + + for (i=0; i < n; i++) { + ktap_value *o = &f->k[i]; + + int t = READ_CHAR(S); + switch (t) { + case KTAP_TNIL: + setnilvalue(o); + break; + case KTAP_TBOOLEAN: + setbvalue(o, READ_CHAR(S)); + break; + case KTAP_TNUMBER: + /* + * todo: kernel not support fp, check double when + * loading + */ + setnvalue(o, READ_NUMBER(S)); + break; + case KTAP_TSTRING: + setsvalue(o, READ_STRING(S)); + break; + default: + kp_error(S->ks, "ktap: load_constants: " + "unknow ktap_value\n"); + return -1; + + } + } + + n = READ_INT(S); + f->p = NEW_VECTOR(S, n * sizeof(ktap_proto)); + f->sizep = n; + for (i = 0; i < n; i++) + f->p[i] = NULL; + for (i = 0; i < n; i++) { + f->p[i] = kp_newproto(S->ks); + if (load_function(S, f->p[i])) + return -1; + } + + return 0; +} + + +static int load_upvalues(struct load_state *S, ktap_proto *f) +{ + int i,n; + + n = READ_INT(S); + f->upvalues = NEW_VECTOR(S, n * sizeof(ktap_upvaldesc)); + f->sizeupvalues = n; + + for (i = 0; i < n; i++) + f->upvalues[i].name = NULL; + + for (i = 0; i < n; i++) { + f->upvalues[i].instack = READ_BYTE(S); + f->upvalues[i].idx = READ_BYTE(S); + } + + return 0; +} + +static int load_debuginfo(struct load_state *S, ktap_proto *f) +{ + int i,n; + + f->source = READ_STRING(S); + n = READ_INT(S); + f->sizelineinfo = n; + f->lineinfo = NEW_VECTOR(S, n * sizeof(int)); + READ_VECTOR(S, f->lineinfo, n * sizeof(int)); + n = READ_INT(S); + f->locvars = NEW_VECTOR(S, n * sizeof(struct ktap_locvar)); + f->sizelocvars = n; + for (i = 0; i < n; i++) + f->locvars[i].varname = NULL; + for (i = 0; i < n; i++) { + f->locvars[i].varname = READ_STRING(S); + f->locvars[i].startpc = READ_INT(S); + f->locvars[i].endpc = READ_INT(S); + } + n = READ_INT(S); + for (i = 0; i < n; i++) + f->upvalues[i].name = READ_STRING(S); + + return 0; +} + +static int load_function(struct load_state *S, ktap_proto *f) +{ + f->linedefined = READ_INT(S); + f->lastlinedefined = READ_INT(S); + f->numparams = READ_BYTE(S); + f->is_vararg = READ_BYTE(S); + f->maxstacksize = READ_BYTE(S); + if (load_code(S, f)) + return -1; + if (load_constants(S, f)) + return -1; + if (load_upvalues(S, f)) + return -1; + if (load_debuginfo(S, f)) + return -1; + + return 0; +} + + +#define error(S, why) \ + kp_error(S->ks, "load failed: %s precompiled chunk\n", why) + +#define N0 KTAPC_HEADERSIZE +#define N1 (sizeof(KTAP_SIGNATURE) - sizeof(char)) +#define N2 N1 + 2 +#define N3 N2 + 6 + +static int load_header(struct load_state *S) +{ + u8 h[KTAPC_HEADERSIZE]; + u8 s[KTAPC_HEADERSIZE]; + + kp_header(h); + READ_VECTOR(S, s, KTAPC_HEADERSIZE); + + if (memcmp(h, s, N0) == 0) + return 0; + if (memcmp(h, s, N1) != 0) + error(S, "not a"); + else if (memcmp(h, s, N2) != 0) + error(S, "version mismatch in"); + else if (memcmp(h, s, N3) != 0) + error(S, "incompatible"); + else + error(S,"corrupted"); + + return -1; +} + + +static int verify_code(struct load_state *S, ktap_proto *f) +{ + /* not support now */ + return 0; +} + + +ktap_closure *kp_load(ktap_state *ks, unsigned char *buff) +{ + struct load_state S; + ktap_closure *cl; + ktap_lclosure *f; + int ret, i; + + S.ks = ks; + S.buff = buff; + S.pos = 0; + + ret = load_header(&S); + if (ret) + return NULL; + + cl = kp_newlclosure(ks, 1); + if (!cl) + return cl; + + /* put closure on the top, prepare to run with this closure */ + setcllvalue(ks->top, cl); + incr_top(ks); + + cl->l.p = kp_newproto(ks); + if (load_function(&S, cl->l.p)) + return NULL; + + if (cl->l.p->sizeupvalues != 1) { + ktap_proto *p = cl->l.p; + cl = kp_newlclosure(ks, cl->l.p->sizeupvalues); + cl->l.p = p; + setcllvalue(ks->top - 1, cl); + } + + f = &cl->l; + for (i = 0; i < f->nupvalues; i++) { /* initialize upvalues */ + ktap_upval *up = kp_newupval(ks); + f->upvals[i] = up; + } + + /* set global table as 1st upvalue of 'f' */ + if (f->nupvalues == 1) { + ktap_table *reg = hvalue(&G(ks)->registry); + const ktap_value *gt = kp_table_getint(reg, KTAP_RIDX_GLOBALS); + setobj(f->upvals[0]->v, gt); + } + + verify_code(&S, cl->l.p); + return cl; +} + diff --git a/drivers/staging/ktap/interpreter/object.c b/drivers/staging/ktap/interpreter/object.c new file mode 100644 index 000000000000..6538167a2b87 --- /dev/null +++ b/drivers/staging/ktap/interpreter/object.c @@ -0,0 +1,483 @@ +/* + * object.c - ktap object generic operation + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * Copyright (C) 1994-2013 Lua.org, PUC-Rio. + * - The part of code in this file is copied from lua initially. + * - lua's MIT license is compatible with GPL. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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. + */ + +#ifdef __KERNEL__ +#include "../include/ktap.h" +#else +#include "../include/ktap_types.h" +#endif + +#ifdef __KERNEL__ + +#define KTAP_ALLOC_FLAGS ((GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN) \ + & ~__GFP_WAIT) + +void *kp_malloc(ktap_state *ks, int size) +{ + void *addr; + + /* + * Normally we don't want to trace under memory pressure, + * so we use a simple rule to handle memory allocation failure: + * + * retry until allocation success, this will make caller don't need + * to handle the unlikely failure case, then ktap exit. + * + * In this approach, if user find there have memory allocation failure, + * user should re-run the ktap script, or fix the memory pressure + * issue, or figure out why the script need so many memory. + * + * Perhaps return pre-allocated stub memory trunk when allocate failed + * is a better approch? + */ + addr = kmalloc(size, KTAP_ALLOC_FLAGS); + if (unlikely(!addr)) { + kp_error(ks, "kmalloc size %d failed, retry again\n", size); + printk("ktap kmalloc size %d failed, retry again\n", size); + dump_stack(); + while (1) { + addr = kmalloc(size, KTAP_ALLOC_FLAGS); + if (addr) + break; + } + kp_printf(ks, "kmalloc retry success after failed, exit\n"); + } + + return addr; +} + +void kp_free(ktap_state *ks, void *addr) +{ + kfree(addr); +} + +void *kp_reallocv(ktap_state *ks, void *addr, int oldsize, int newsize) +{ + void *new_addr; + + new_addr = krealloc(addr, newsize, KTAP_ALLOC_FLAGS); + if (unlikely(!new_addr)) { + kp_error(ks, "krealloc size %d failed, retry again\n", newsize); + printk("ktap krealloc size %d failed, retry again\n", newsize); + dump_stack(); + while (1) { + new_addr = krealloc(addr, newsize, KTAP_ALLOC_FLAGS); + if (new_addr) + break; + } + kp_printf(ks, "krealloc retry success after failed, exit\n"); + } + + return new_addr; +} + +void *kp_zalloc(ktap_state *ks, int size) +{ + void *addr; + + addr = kzalloc(size, KTAP_ALLOC_FLAGS); + if (unlikely(!addr)) { + kp_error(ks, "kzalloc size %d failed, retry again\n", size); + printk("ktap kzalloc size %d failed, retry again\n", size); + dump_stack(); + while (1) { + addr = kzalloc(size, KTAP_ALLOC_FLAGS); + if (addr) + break; + } + kp_printf(ks, "kzalloc retry success after failed, exit\n"); + } + + return addr; +} +#endif + +void kp_obj_dump(ktap_state *ks, const ktap_value *v) +{ + switch (ttype(v)) { + case KTAP_TNIL: + kp_puts(ks, "NIL"); + break; + case KTAP_TNUMBER: + kp_printf(ks, "NUMBER %ld", nvalue(v)); + break; + case KTAP_TBOOLEAN: + kp_printf(ks, "BOOLEAN %d", bvalue(v)); + break; + case KTAP_TLIGHTUSERDATA: + kp_printf(ks, "LIGHTUSERDATA 0x%lx", (unsigned long)pvalue(v)); + break; + case KTAP_TLCF: + kp_printf(ks, "LIGHTCFCUNTION 0x%lx", (unsigned long)fvalue(v)); + break; + case KTAP_TSHRSTR: + case KTAP_TLNGSTR: + kp_printf(ks, "SHRSTR #%s", svalue(v)); + break; + case KTAP_TUSERDATA: + kp_printf(ks, "USERDATA 0x%lx", (unsigned long)uvalue(v)); + break; + case KTAP_TTABLE: + kp_printf(ks, "TABLE 0x%lx", (unsigned long)hvalue(v)); + break; + default: + kp_printf(ks, "GCVALUE 0x%lx", (unsigned long)gcvalue(v)); + break; + } +} + +#ifdef __KERNEL__ +#include <linux/stacktrace.h> +#include <linux/kallsyms.h> + +static void kp_btrace_dump(ktap_state *ks, ktap_btrace *bt) +{ + char str[KSYM_SYMBOL_LEN]; + int i; + + for (i = 0; i < bt->nr_entries; i++) { + unsigned long p = bt->entries[i]; + + if (p == ULONG_MAX) + break; + + SPRINT_SYMBOL(str, p); + kp_printf(ks, "%s\n", str); + } +} + +static int kp_btrace_equal(ktap_btrace *bt1, ktap_btrace *bt2) +{ + int i; + + if (bt1->nr_entries != bt2->nr_entries) + return 0; + + for (i = 0; i < bt1->nr_entries; i++) { + if (bt1->entries[i] != bt2->entries[i]) + return 0; + } + + return 1; +} +#endif + +void kp_showobj(ktap_state *ks, const ktap_value *v) +{ + switch (ttype(v)) { + case KTAP_TNIL: + kp_puts(ks, "nil"); + break; + case KTAP_TNUMBER: + kp_printf(ks, "%ld", nvalue(v)); + break; + case KTAP_TBOOLEAN: + kp_puts(ks, (bvalue(v) == 1) ? "true" : "false"); + break; + case KTAP_TLIGHTUSERDATA: + kp_printf(ks, "0x%lx", (unsigned long)pvalue(v)); + break; + case KTAP_TLCF: + kp_printf(ks, "0x%lx", (unsigned long)fvalue(v)); + break; + case KTAP_TSHRSTR: + case KTAP_TLNGSTR: + kp_puts(ks, svalue(v)); + break; + case KTAP_TUSERDATA: + kp_printf(ks, "0x%lx", (unsigned long)uvalue(v)); + break; + case KTAP_TTABLE: + kp_table_dump(ks, hvalue(v)); + break; +#ifdef __KERNEL__ + case KTAP_TEVENT: + kp_transport_event_write(ks, evalue(v)); + break; + case KTAP_TBTRACE: + kp_btrace_dump(ks, btvalue(v)); + break; + case KTAP_TAGGRTABLE: + kp_aggrtable_dump(ks, ahvalue(v)); + break; + case KTAP_TAGGRACCVAL: + kp_aggraccval_dump(ks, aggraccvalue(v)); + break; +#endif + default: + kp_error(ks, "print unknown value type: %d\n", ttype(v)); + break; + } +} + + +/* + * equality of ktap values. ks == NULL means raw equality + */ +int kp_equalobjv(ktap_state *ks, const ktap_value *t1, const ktap_value *t2) +{ + switch (ttype(t1)) { + case KTAP_TNIL: + return 1; + case KTAP_TNUMBER: + return nvalue(t1) == nvalue(t2); + case KTAP_TBOOLEAN: + return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ + case KTAP_TLIGHTUSERDATA: + return pvalue(t1) == pvalue(t2); + case KTAP_TLCF: + return fvalue(t1) == fvalue(t2); + case KTAP_TSHRSTR: + return eqshrstr(rawtsvalue(t1), rawtsvalue(t2)); + case KTAP_TLNGSTR: + return kp_tstring_eqlngstr(rawtsvalue(t1), rawtsvalue(t2)); + case KTAP_TUSERDATA: + if (uvalue(t1) == uvalue(t2)) + return 1; + else if (ks == NULL) + return 0; + case KTAP_TTABLE: + if (hvalue(t1) == hvalue(t2)) + return 1; + else if (ks == NULL) + return 0; +#ifdef __KERNEL__ + case KTAP_TBTRACE: + return kp_btrace_equal(btvalue(t1), btvalue(t2)); +#endif + default: + return gcvalue(t1) == gcvalue(t2); + } + + return 0; +} + +/* + * ktap will not use lua's length operator on table meaning, + * also # is not for length operator any more in ktap. + * + * Quote from lua mannal: + * 2.5.5 - The Length Operator + * + * The length operator is denoted by the unary operator #. + * The length of a string is its number of bytes(that is, + * the usual meaning of string length when each character is one byte). + * + * The length of a table t is defined to be any integer index n + * such that t[n] is not nil and t[n+1] is nil; moreover, if t[1] is nil, + * n can be zero. For a regular array, with non-nil values from 1 to a given n, + * its length is exactly that n, the index of its last value. If the array has + * "holes" (that is, nil values between other non-nil values), then #t can be + * any of the indices that directly precedes a nil value + * (that is, it may consider any such nil value as the end of the array). + */ +int kp_objlen(ktap_state *ks, const ktap_value *v) +{ + switch(v->type) { + case KTAP_TTABLE: + return kp_table_length(ks, hvalue(v)); + case KTAP_TSTRING: + return rawtsvalue(v)->tsv.len; + default: + kp_printf(ks, "cannot get length of type %d\n", v->type); + return -1; + } + return 0; +} + +/* need to protect allgc field? */ +ktap_gcobject *kp_newobject(ktap_state *ks, int type, size_t size, + ktap_gcobject **list) +{ + ktap_gcobject *o; + + o = kp_malloc(ks, size); + if (list == NULL) + list = &G(ks)->allgc; + + gch(o)->tt = type; + gch(o)->next = *list; + *list = o; + + return o; +} + +ktap_upval *kp_newupval(ktap_state *ks) +{ + ktap_upval *uv; + + uv = &kp_newobject(ks, KTAP_TUPVAL, sizeof(ktap_upval), NULL)->uv; + uv->v = &uv->u.value; + setnilvalue(uv->v); + return uv; +} + +static ktap_btrace *kp_newbacktrace(ktap_state *ks, ktap_gcobject **list) +{ + ktap_btrace *bt; + + bt = &kp_newobject(ks, KTAP_TBTRACE, sizeof(ktap_btrace), list)->bt; + return bt; +} + +void kp_objclone(ktap_state *ks, const ktap_value *o, ktap_value *newo, + ktap_gcobject **list) +{ + if (ttisbtrace(o)) { + ktap_btrace *bt; + bt = kp_newbacktrace(ks, list); + bt->nr_entries = btvalue(o)->nr_entries; + memcpy(&bt->entries[0], &btvalue(o)->entries[0], + sizeof(bt->entries)); + setbtvalue(newo, bt); + } else { + kp_error(ks, "cannot clone ktap value type %d\n", ttype(o)); + setnilvalue(newo); + } +} + +ktap_closure *kp_newlclosure(ktap_state *ks, int n) +{ + ktap_closure *cl; + + cl = (ktap_closure *)kp_newobject(ks, KTAP_TLCL, sizeof(*cl), NULL); + cl->l.p = NULL; + cl->l.nupvalues = n; + while (n--) + cl->l.upvals[n] = NULL; + + return cl; +} + +static void free_proto(ktap_state *ks, ktap_proto *f) +{ + kp_free(ks, f->code); + kp_free(ks, f->p); + kp_free(ks, f->k); + kp_free(ks, f->lineinfo); + kp_free(ks, f->locvars); + kp_free(ks, f->upvalues); + kp_free(ks, f); +} + +ktap_proto *kp_newproto(ktap_state *ks) +{ + ktap_proto *f; + f = (ktap_proto *)kp_newobject(ks, KTAP_TPROTO, sizeof(*f), NULL); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->cache = NULL; + f->sizecode = 0; + f->lineinfo = NULL; + f->sizelineinfo = 0; + f->upvalues = NULL; + f->sizeupvalues = 0; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->locvars = NULL; + f->sizelocvars = 0; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + +static ktap_udata *newudata(ktap_state *ks, size_t s) +{ + ktap_udata *u; + + u = &kp_newobject(ks, KTAP_TUSERDATA, sizeof(ktap_udata) + s, NULL)->u; + u->uv.len = s; + return u; +} + +void *kp_newuserdata(ktap_state *ks, size_t size) +{ + ktap_udata *u; + + u = newudata(ks, size); + return u + 1; +} + +void kp_free_gclist(ktap_state *ks, ktap_gcobject *o) +{ + while (o) { + ktap_gcobject *next; + + next = gch(o)->next; + switch (gch(o)->tt) { + case KTAP_TTABLE: + kp_table_free(ks, (ktap_table *)o); + break; + case KTAP_TPROTO: + free_proto(ks, (ktap_proto *)o); + break; +#ifdef __KERNEL__ + case KTAP_TAGGRTABLE: + kp_aggrtable_free(ks, (ktap_aggrtable *)o); + break; +#endif + default: + kp_free(ks, o); + } + o = next; + } +} + +void kp_free_all_gcobject(ktap_state *ks) +{ + kp_free_gclist(ks, G(ks)->allgc); + G(ks)->allgc = NULL; +} + +/******************************************************************************/ + +/* + * make header for precompiled chunks + * if you change the code below be sure to update load_header and FORMAT above + * and KTAPC_HEADERSIZE in ktap_types.h + */ +void kp_header(u8 *h) +{ + int x = 1; + + memcpy(h, KTAP_SIGNATURE, sizeof(KTAP_SIGNATURE) - sizeof(char)); + h += sizeof(KTAP_SIGNATURE) - sizeof(char); + *h++ = (u8)VERSION; + *h++ = (u8)FORMAT; + *h++ = (u8)(*(char*)&x); /* endianness */ + *h++ = (u8)(sizeof(int)); + *h++ = (u8)(sizeof(size_t)); + *h++ = (u8)(sizeof(ktap_instruction)); + *h++ = (u8)(sizeof(ktap_number)); + *h++ = (u8)(((ktap_number)0.5) == 0); /* is ktap_number integral? */ + memcpy(h, KTAPC_TAIL, sizeof(KTAPC_TAIL) - sizeof(char)); +} + + diff --git a/drivers/staging/ktap/interpreter/opcode.c b/drivers/staging/ktap/interpreter/opcode.c new file mode 100644 index 000000000000..2f44855fcad2 --- /dev/null +++ b/drivers/staging/ktap/interpreter/opcode.c @@ -0,0 +1,127 @@ +/* + * opcode.c + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * Copyright (C) 1994-2013 Lua.org, PUC-Rio. + * - The part of code in this file is copied from lua initially. + * - lua's MIT license is compatible with GPL. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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/ktap_types.h" +#include "../include/ktap_opcodes.h" + +const char *const ktap_opnames[NUM_OPCODES + 1] = { + "MOVE", + "LOADK", + "LOADKX", + "LOADBOOL", + "LOADNIL", + "GETUPVAL", + "GETTABUP", + "GETTABLE", + "SETTABUP", + "SETTABUP_INCR", + "SETUPVAL", + "SETTABLE", + "SETTABLE_INCR", + "NEWTABLE", + "SELF", + "ADD", + "SUB", + "MUL", + "DIV", + "MOD", + "POW", + "UNM", + "NOT", + "LEN", + "CONCAT", + "JMP", + "EQ", + "LT", + "LE", + "TEST", + "TESTSET", + "CALL", + "TAILCALL", + "RETURN", + "FORLOOP", + "FORPREP", + "TFORCALL", + "TFORLOOP", + "SETLIST", + "CLOSURE", + "VARARG", + "EXTRAARG", + + "EVENT", + "EVENT_NAME", + "EVENT_ARG", /* arg1, arg2 .. arg9 */ + NULL +}; + + +#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) + +const u8 ktap_opmodes[NUM_OPCODES] = { +/* T A B C mode opcode */ + opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ + ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ + ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ + ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ + ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ + ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ + ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ + ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ + ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ + ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_EVENT */ +}; + + diff --git a/drivers/staging/ktap/interpreter/strfmt.c b/drivers/staging/ktap/interpreter/strfmt.c new file mode 100644 index 000000000000..2c1e7618fef4 --- /dev/null +++ b/drivers/staging/ktap/interpreter/strfmt.c @@ -0,0 +1,196 @@ +/* + * strfmt.c - printf implementation + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * Copyright (C) 1994-2013 Lua.org, PUC-Rio. + * - The part of code in this file is copied from lua initially. + * - lua's MIT license is compatible with GPL. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <linux/ctype.h> +#include <linux/kallsyms.h> +#include "../include/ktap.h" + +/* macro to `unsign' a character */ +#define uchar(c) ((unsigned char)(c)) + +#define L_ESC '%' + +/* valid flags in a format specification */ +#define FLAGS "-+ #0" + +#define INTFRMLEN "ll" +#define INTFRM_T long long + +/* + * maximum size of each format specification (such as '%-099.99d') + * (+10 accounts for %99.99x plus margin of error) + */ +#define MAX_FORMAT (sizeof(FLAGS) + sizeof(INTFRMLEN) + 10) + +static const char *scanformat(ktap_state *ks, const char *strfrmt, char *form) +{ + const char *p = strfrmt; + while (*p != '\0' && strchr(FLAGS, *p) != NULL) + p++; /* skip flags */ + + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) { + kp_error(ks, "invalid format (repeated flags)\n"); + return NULL; + } + + if (isdigit(uchar(*p))) + p++; /* skip width */ + + if (isdigit(uchar(*p))) + p++; /* (2 digits at most) */ + + if (*p == '.') { + p++; + if (isdigit(uchar(*p))) + p++; /* skip precision */ + if (isdigit(uchar(*p))) + p++; /* (2 digits at most) */ + } + + if (isdigit(uchar(*p))) { + kp_error(ks, "invalid format (width or precision too long)\n"); + return NULL; + } + + *(form++) = '%'; + memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); + form += p - strfrmt + 1; + *form = '\0'; + return p; +} + + +/* + * add length modifier into formats + */ +static void addlenmod(char *form, const char *lenmod) +{ + size_t l = strlen(form); + size_t lm = strlen(lenmod); + char spec = form[l - 1]; + + strcpy(form + l - 1, lenmod); + form[l + lm - 1] = spec; + form[l + lm] = '\0'; +} + + +static void ktap_argerror(ktap_state *ks, int narg, const char *extramsg) +{ + kp_error(ks, "bad argument #%d: (%s)\n", narg, extramsg); +} + +int kp_strfmt(ktap_state *ks, struct trace_seq *seq) +{ + int arg = 1; + size_t sfl; + ktap_value *arg_fmt = kp_arg(ks, 1); + int argnum = kp_arg_nr(ks); + const char *strfrmt, *strfrmt_end; + + strfrmt = svalue(arg_fmt); + sfl = rawtsvalue(arg_fmt)->tsv.len; + strfrmt_end = strfrmt + sfl; + + while (strfrmt < strfrmt_end) { + if (*strfrmt != L_ESC) + trace_seq_putc(seq, *strfrmt++); + else if (*++strfrmt == L_ESC) + trace_seq_putc(seq, *strfrmt++); + else { /* format item */ + char form[MAX_FORMAT]; + + if (++arg > argnum) { + ktap_argerror(ks, arg, "no value"); + return -1; + } + + strfrmt = scanformat(ks, strfrmt, form); + switch (*strfrmt++) { + case 'c': + trace_seq_printf(seq, form, + nvalue(kp_arg(ks, arg))); + break; + case 'd': case 'i': { + ktap_number n = nvalue(kp_arg(ks, arg)); + INTFRM_T ni = (INTFRM_T)n; + addlenmod(form, INTFRMLEN); + trace_seq_printf(seq, form, ni); + break; + } + case 'p': { + char str[KSYM_SYMBOL_LEN]; + SPRINT_SYMBOL(str, nvalue(kp_arg(ks, arg))); + trace_seq_puts(seq, str); + break; + } + case 'o': case 'u': case 'x': case 'X': { + ktap_number n = nvalue(kp_arg(ks, arg)); + unsigned INTFRM_T ni = (unsigned INTFRM_T)n; + addlenmod(form, INTFRMLEN); + trace_seq_printf(seq, form, ni); + break; + } + case 's': { + ktap_value *v = kp_arg(ks, arg); + const char *s; + size_t l; + + if (isnil(v)) { + trace_seq_puts(seq, "nil"); + return 0; + } + + if (ttisevent(v)) { + kp_event_tostring(ks, seq); + return 0; + } + + s = svalue(v); + l = rawtsvalue(v)->tsv.len; + if (!strchr(form, '.') && l >= 100) { + /* + * no precision and string is too long + * to be formatted; + * keep original string + */ + trace_seq_puts(seq, s); + break; + } else { + trace_seq_printf(seq, form, s); + break; + } + } + default: /* also treat cases `pnLlh' */ + kp_error(ks, "invalid option " KTAP_QL("%%%c") + " to " KTAP_QL("format"), + *(strfrmt - 1)); + } + } + } + + return 0; +} + diff --git a/drivers/staging/ktap/interpreter/table.c b/drivers/staging/ktap/interpreter/table.c new file mode 100644 index 000000000000..4e83947ba02d --- /dev/null +++ b/drivers/staging/ktap/interpreter/table.c @@ -0,0 +1,1292 @@ +/* + * table.c - ktap table data structure manipulation function + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * Copyright (C) 1994-2013 Lua.org, PUC-Rio. + * - The part of code in this file is copied from lua initially. + * - lua's MIT license is compatible with GPL. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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. + */ + +#ifdef __KERNEL__ +#include "../include/ktap.h" +#include <linux/spinlock.h> +#include <linux/kallsyms.h> +#include <linux/sort.h> +#else +#include "../include/ktap_types.h" + +static inline void sort(void *base, size_t num, size_t size, + int (*cmp_func)(const void *, const void *), + void (*swap_func)(void *, void *, int size)) +{} +#endif + + +#ifdef __KERNEL__ +#define kp_table_lock_init(t) \ + do { \ + t->lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; \ + } while (0) +#define kp_table_lock(t) \ + do { \ + local_irq_save(flags); \ + arch_spin_lock(&t->lock); \ + } while (0) +#define kp_table_unlock(t) \ + do { \ + arch_spin_unlock(&t->lock); \ + local_irq_restore(flags); \ + } while (0) + +#else +#define kp_table_lock_init(t) +#define kp_table_lock(t) +#define kp_table_unlock(t) +#endif + +#define MAXBITS 30 +#define MAXASIZE (1 << MAXBITS) + + +#define NILCONSTANT {NULL}, KTAP_TNIL +const struct ktap_value ktap_nilobjectv = {NILCONSTANT}; +#define ktap_nilobject (&ktap_nilobjectv) + +static const ktap_tnode dummynode_ = { + {NILCONSTANT}, /* value */ + {{NILCONSTANT, NULL}}, /* key */ +}; + +#define gnode(t,i) (&(t)->node[i]) +#define gkey(n) (&(n)->i_key.tvk) +#define gval(n) (&(n)->i_val) +#define gnext(n) ((n)->i_key.nk.next) + +#define twoto(x) (1<<(x)) +#define sizenode(t) (twoto((t)->lsizenode)) + +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) + +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) + +#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) +#define hashboolean(t,p) hashpow2(t, p) +#define hashnum(t, n) hashmod(t, (unsigned int)n) +#define hashpointer(t,p) hashmod(t, (unsigned long)(p)) + +#define dummynode (&dummynode_) +#define isdummy(n) ((n) == dummynode) + +static void table_setint(ktap_state *ks, ktap_table *t, int key, ktap_value *v); +static ktap_value *table_set(ktap_state *ks, ktap_table *t, + const ktap_value *key); +static void setnodevector(ktap_state *ks, ktap_table *t, int size); + +static int ceillog2(unsigned int x) +{ + static const u8 log_2[256] = { + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }; + + int l = 0; + + x--; + while (x >= 256) { l += 8; x >>= 8; } + return l + log_2[x]; +} + + +ktap_table *kp_table_new(ktap_state *ks) +{ + ktap_table *t = &kp_newobject(ks, KTAP_TTABLE, sizeof(ktap_table), + NULL)->h; + t->flags = (u8)(~0); + t->array = NULL; + t->sizearray = 0; + t->node = (ktap_tnode *)dummynode; + t->gclist = NULL; + setnodevector(ks, t, 0); + + kp_table_lock_init(t); + return t; +} + +static const ktap_value *table_getint(ktap_table *t, int key) +{ + ktap_tnode *n; + + if ((unsigned int)(key - 1) < (unsigned int)t->sizearray) + return &t->array[key - 1]; + + n = hashnum(t, key); + do { + if (ttisnumber(gkey(n)) && nvalue(gkey(n)) == key) + return gval(n); + else + n = gnext(n); + } while (n); + + return ktap_nilobject; +} + +const ktap_value *kp_table_getint(ktap_table *t, int key) +{ + const ktap_value *val; + unsigned long __maybe_unused flags; + + kp_table_lock(t); + val = table_getint(t, key); + kp_table_unlock(t); + + return val; +} + +static ktap_tnode *mainposition (const ktap_table *t, const ktap_value *key) +{ + switch (ttype(key)) { + case KTAP_TNUMBER: + return hashnum(t, nvalue(key)); + case KTAP_TLNGSTR: { + ktap_string *s = rawtsvalue(key); + if (s->tsv.extra == 0) { /* no hash? */ + s->tsv.hash = kp_string_hash(getstr(s), s->tsv.len, + s->tsv.hash); + s->tsv.extra = 1; /* now it has its hash */ + } + return hashstr(t, rawtsvalue(key)); + } + case KTAP_TSHRSTR: + return hashstr(t, rawtsvalue(key)); + case KTAP_TBOOLEAN: + return hashboolean(t, bvalue(key)); + case KTAP_TLIGHTUSERDATA: + return hashpointer(t, pvalue(key)); + case KTAP_TLCF: + return hashpointer(t, fvalue(key)); + case KTAP_TBTRACE: + /* use first entry as hash key, cannot use gcvalue as key */ + return hashpointer(t, btvalue(key)->entries[0]); + default: + return hashpointer(t, gcvalue(key)); + } +} + +static int arrayindex(const ktap_value *key) +{ + if (ttisnumber(key)) { + ktap_number n = nvalue(key); + int k = (int)n; + if ((ktap_number)k == n) + return k; + } + + /* `key' did not match some condition */ + return -1; +} + +/* + * returns the index of a `key' for table traversals. First goes all + * elements in the array part, then elements in the hash part. The + * beginning of a traversal is signaled by -1. + */ +static int findindex(ktap_state *ks, ktap_table *t, StkId key) +{ + int i; + + if (ttisnil(key)) + return -1; /* first iteration */ + + i = arrayindex(key); + if (i > 0 && i <= t->sizearray) /* is `key' inside array part? */ + return i - 1; /* yes; that's the index (corrected to C) */ + else { + ktap_tnode *n = mainposition(t, key); + for (;;) { /* check whether `key' is somewhere in the chain */ + /* key may be dead already, but it is ok to use it in `next' */ + if (kp_equalobjv(ks, gkey(n), key)) { + i = n - gnode(t, 0); /* key index in hash table */ + /* hash elements are numbered after array ones */ + return i + t->sizearray; + } else + n = gnext(n); + + if (n == NULL) + /* key not found */ + kp_error(ks, "invalid table key to next"); + } + } +} + +int kp_table_next(ktap_state *ks, ktap_table *t, StkId key) +{ + unsigned long __maybe_unused flags; + int i; + + kp_table_lock(t); + + i = findindex(ks, t, key); /* find original element */ + + for (i++; i < t->sizearray; i++) { /* try first array part */ + if (!ttisnil(&t->array[i])) { /* a non-nil value? */ + setnvalue(key, i+1); + setobj(key+1, &t->array[i]); + kp_table_unlock(t); + return 1; + } + } + + for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ + if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ + setobj(key, gkey(gnode(t, i))); + setobj(key+1, gval(gnode(t, i))); + kp_table_unlock(t); + return 1; + } + } + + kp_table_unlock(t); + return 0; /* no more elements */ +} + + + +static int computesizes (int nums[], int *narray) +{ + int i; + int twotoi; /* 2^i */ + int a = 0; /* number of elements smaller than 2^i */ + int na = 0; /* number of elements to go to array part */ + int n = 0; /* optimal size for array part */ + + for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { + if (nums[i] > 0) { + a += nums[i]; + /* more than half elements present? */ + if (a > twotoi/2) { + /* optimal size (till now) */ + n = twotoi; + /* + * all elements smaller than n will go to + * array part + */ + na = a; + } + } + if (a == *narray) + break; /* all elements already counted */ + } + *narray = n; + return na; +} + + +static int countint(const ktap_value *key, int *nums) +{ + int k = arrayindex(key); + + /* is `key' an appropriate array index? */ + if (0 < k && k <= MAXASIZE) { + nums[ceillog2(k)]++; /* count as such */ + return 1; + } else + return 0; +} + + +static int numusearray(const ktap_table *t, int *nums) +{ + int lg; + int ttlg; /* 2^lg */ + int ause = 0; /* summation of `nums' */ + int i = 1; /* count to traverse all array keys */ + + /* for each slice */ + for (lg=0, ttlg=1; lg <= MAXBITS; lg++, ttlg *= 2) { + int lc = 0; /* counter */ + int lim = ttlg; + + if (lim > t->sizearray) { + lim = t->sizearray; /* adjust upper limit */ + if (i > lim) + break; /* no more elements to count */ + } + + /* count elements in range (2^(lg-1), 2^lg] */ + for (; i <= lim; i++) { + if (!ttisnil(&t->array[i-1])) + lc++; + } + nums[lg] += lc; + ause += lc; + } + return ause; +} + +static int numusehash(const ktap_table *t, int *nums, int *pnasize) +{ + int totaluse = 0; /* total number of elements */ + int ause = 0; /* summation of `nums' */ + int i = sizenode(t); + + while (i--) { + ktap_tnode *n = &t->node[i]; + if (!isnil(gval(n))) { + ause += countint(gkey(n), nums); + totaluse++; + } + } + + *pnasize += ause; + return totaluse; +} + + +static void setarrayvector(ktap_state *ks, ktap_table *t, int size) +{ + int i; + + kp_realloc(ks, t->array, t->sizearray, size, ktap_value); + for (i = t->sizearray; i < size; i++) + setnilvalue(&t->array[i]); + + t->sizearray = size; +} + +static void setnodevector(ktap_state *ks, ktap_table *t, int size) +{ + int lsize; + + if (size == 0) { /* no elements to hash part? */ + t->node = (ktap_tnode *)dummynode; /* use common `dummynode' */ + lsize = 0; + } else { + int i; + lsize = ceillog2(size); + if (lsize > MAXBITS) { + kp_error(ks, "table overflow\n"); + return; + } + + size = twoto(lsize); + t->node = kp_malloc(ks, size * sizeof(ktap_tnode)); + for (i = 0; i < size; i++) { + ktap_tnode *n = gnode(t, i); + gnext(n) = NULL; + setnilvalue(gkey(n)); + setnilvalue(gval(n)); + } + } + + t->lsizenode = (u8)lsize; + t->lastfree = gnode(t, size); /* all positions are free */ +} + +static void table_resize(ktap_state *ks, ktap_table *t, int nasize, int nhsize) +{ + int i; + int oldasize = t->sizearray; + int oldhsize = t->lsizenode; + ktap_tnode *nold = t->node; /* save old hash ... */ + +#ifdef __KERNEL__ + kp_verbose_printf(ks, "table resize, nasize: %d, nhsize: %d\n", + nasize, nhsize); +#endif + + if (nasize > oldasize) /* array part must grow? */ + setarrayvector(ks, t, nasize); + + /* create new hash part with appropriate size */ + setnodevector(ks, t, nhsize); + + if (nasize < oldasize) { /* array part must shrink? */ + t->sizearray = nasize; + /* re-insert elements from vanishing slice */ + for (i=nasize; i<oldasize; i++) { + if (!ttisnil(&t->array[i])) + table_setint(ks, t, i + 1, &t->array[i]); + } + + /* shrink array */ + kp_realloc(ks, t->array, oldasize, nasize, ktap_value); + } + + /* re-insert elements from hash part */ + for (i = twoto(oldhsize) - 1; i >= 0; i--) { + ktap_tnode *old = nold+i; + if (!ttisnil(gval(old))) { + /* + * doesn't need barrier/invalidate cache, as entry was + * already present in the table + */ + setobj(table_set(ks, t, gkey(old)), gval(old)); + } + } + + if (!isdummy(nold)) + kp_free(ks, nold); /* free old array */ +} + +void kp_table_resize(ktap_state *ks, ktap_table *t, int nasize, int nhsize) +{ + unsigned long __maybe_unused flags; + + kp_table_lock(t); + table_resize(ks, t, nasize, nhsize); + kp_table_unlock(t); +} + +void kp_table_resizearray(ktap_state *ks, ktap_table *t, int nasize) +{ + unsigned long __maybe_unused flags; + int nsize; + + kp_table_lock(t); + + nsize = isdummy(t->node) ? 0 : sizenode(t); + table_resize(ks, t, nasize, nsize); + + kp_table_unlock(t); +} + +static void rehash(ktap_state *ks, ktap_table *t, const ktap_value *ek) +{ + int nasize, na; + /* nums[i] = number of keys with 2^(i-1) < k <= 2^i */ + int nums[MAXBITS+1]; + int i; + int totaluse; + + for (i = 0; i <= MAXBITS; i++) + nums[i] = 0; /* reset counts */ + + nasize = numusearray(t, nums); /* count keys in array part */ + totaluse = nasize; /* all those keys are integer keys */ + totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ + /* count extra key */ + nasize += countint(ek, nums); + totaluse++; + /* compute new size for array part */ + na = computesizes(nums, &nasize); + /* resize the table to new computed sizes */ + table_resize(ks, t, nasize, totaluse - na); +} + + +static ktap_tnode *getfreepos(ktap_table *t) +{ + while (t->lastfree > t->node) { + t->lastfree--; + if (isnil(gkey(t->lastfree))) + return t->lastfree; + } + return NULL; /* could not find a free place */ +} + + +static ktap_value *table_newkey(ktap_state *ks, ktap_table *t, + const ktap_value *key) +{ + ktap_tnode *mp; + ktap_value newkey; + + mp = mainposition(t, key); + if (!isnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ + ktap_tnode *othern; + ktap_tnode *n = getfreepos(t); /* get a free place */ + if (n == NULL) { /* cannot find a free place? */ + rehash(ks, t, key); /* grow table */ + /* whatever called 'newkey' take care of TM cache and GC barrier */ + return table_set(ks, t, key); /* insert key into grown table */ + } + + othern = mainposition(t, gkey(mp)); + if (othern != mp) { /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ + while (gnext(othern) != mp) + othern = gnext(othern); /* find previous */ + gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ + *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + gnext(mp) = NULL; /* now `mp' is free */ + setnilvalue(gval(mp)); + } else { /* colliding node is in its own main position */ + /* new node will go into free position */ + gnext(n) = gnext(mp); /* chain new position */ + gnext(mp) = n; + mp = n; + } + } + + /* special handling for cloneable object, maily for btrace object */ + if (ttisclone(key)) + kp_objclone(ks, key, &newkey, &t->gclist); + else + newkey = *key; + + setobj(gkey(mp), &newkey); + return gval(mp); +} + + +/* + * search function for short strings + */ +static const ktap_value *table_getstr(ktap_table *t, ktap_string *key) +{ + ktap_tnode *n = hashstr(t, key); + + do { /* check whether `key' is somewhere in the chain */ + if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), + key)) + return gval(n); /* that's it */ + else + n = gnext(n); + } while (n); + + return ktap_nilobject; +} + + +/* + * main search function + */ +static const ktap_value *table_get(ktap_table *t, const ktap_value *key) +{ + switch (ttype(key)) { + case KTAP_TNIL: + return ktap_nilobject; + case KTAP_TSHRSTR: + return table_getstr(t, rawtsvalue(key)); + case KTAP_TNUMBER: { + ktap_number n = nvalue(key); + int k = (int)n; + if ((ktap_number)k == nvalue(key)) /* index is int? */ + return table_getint(t, k); /* use specialized version */ + /* else go through */ + } + default: { + ktap_tnode *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (rawequalobj(gkey(n), key)) + return gval(n); /* that's it */ + else + n = gnext(n); + } while (n); + + return ktap_nilobject; + } + } +} + +const ktap_value *kp_table_get(ktap_table *t, const ktap_value *key) +{ + const ktap_value *val; + unsigned long __maybe_unused flags; + + kp_table_lock(t); + val = table_get(t, key); + kp_table_unlock(t); + + return val; +} + +static ktap_value *table_set(ktap_state *ks, ktap_table *t, + const ktap_value *key) +{ + const ktap_value *p = table_get(t, key); + + if (p != ktap_nilobject) + return (ktap_value *)p; + else + return table_newkey(ks, t, key); +} + +void kp_table_setvalue(ktap_state *ks, ktap_table *t, + const ktap_value *key, ktap_value *val) +{ + unsigned long __maybe_unused flags; + + if (isnil(key)) { + kp_printf(ks, "table index is nil\n"); + kp_exit(ks); + return; + } + + kp_table_lock(t); + setobj(table_set(ks, t, key), val); + kp_table_unlock(t); +} + +static void table_setint(ktap_state *ks, ktap_table *t, int key, ktap_value *v) +{ + const ktap_value *p; + ktap_value *cell; + + p = table_getint(t, key); + + if (p != ktap_nilobject) + cell = (ktap_value *)p; + else { + ktap_value k; + setnvalue(&k, key); + cell = table_newkey(ks, t, &k); + } + + setobj(cell, v); +} + +void kp_table_setint(ktap_state *ks, ktap_table *t, int key, ktap_value *val) +{ + unsigned long __maybe_unused flags; + + kp_table_lock(t); + table_setint(ks, t, key, val); + kp_table_unlock(t); +} + +void kp_table_atomic_inc(ktap_state *ks, ktap_table *t, ktap_value *key, int n) +{ + unsigned long __maybe_unused flags; + ktap_value *v; + + if (isnil(key)) { + kp_printf(ks, "table index is nil\n"); + kp_exit(ks); + return; + } + + kp_table_lock(t); + + v = table_set(ks, t, key); + if (isnil(v)) { + setnvalue(v, n); + } else + setnvalue(v, nvalue(v) + n); + + kp_table_unlock(t); +} + +int kp_table_length(ktap_state *ks, ktap_table *t) +{ + unsigned long __maybe_unused flags; + int i, len = 0; + + kp_table_lock(t); + + for (i = 0; i < t->sizearray; i++) { + ktap_value *v = &t->array[i]; + + if (isnil(v)) + continue; + len++; + } + + for (i = 0; i < sizenode(t); i++) { + ktap_tnode *n = &t->node[i]; + + if (isnil(gkey(n))) + continue; + + len++; + } + + kp_table_unlock(t); + return len; +} + +void kp_table_free(ktap_state *ks, ktap_table *t) +{ + if (t->sizearray > 0) + kp_free(ks, t->array); + if (!isdummy(t->node)) + kp_free(ks, t->node); + + kp_free_gclist(ks, t->gclist); + kp_free(ks, t); +} + +void kp_table_dump(ktap_state *ks, ktap_table *t) +{ + int i, count = 0; + + kp_puts(ks, "{"); + for (i = 0; i < t->sizearray; i++) { + ktap_value *v = &t->array[i]; + + if (isnil(v)) + continue; + + if (count) + kp_puts(ks, ", "); + + kp_printf(ks, "(%d: ", i + 1); + kp_showobj(ks, v); + kp_puts(ks, ")"); + count++; + } + + for (i = 0; i < sizenode(t); i++) { + ktap_tnode *n = &t->node[i]; + + if (isnil(gkey(n))) + continue; + + if (count) + kp_puts(ks, ", "); + + kp_puts(ks, "("); + kp_showobj(ks, gkey(n)); + kp_puts(ks, ": "); + kp_showobj(ks, gval(n)); + kp_puts(ks, ")"); + count++; + } + kp_puts(ks, "}"); +} + +/* + * table-clear only set nil of all elements, not free t->array and nodes. + * we assume user will reuse table soon after clear table, so reserve array + * and nodes will avoid memory allocation when insert key-value again. + */ +void kp_table_clear(ktap_state *ks, ktap_table *t) +{ + unsigned long __maybe_unused flags; + int i; + + kp_table_lock(t); + + for (i = 0; i < t->sizearray; i++) { + ktap_value *v = &t->array[i]; + + if (isnil(v)) + continue; + + setnilvalue(v); + } + + for (i = 0; i < sizenode(t); i++) { + ktap_tnode *n = &t->node[i]; + + if (isnil(gkey(n))) + continue; + + setnilvalue(gkey(n)); + setnilvalue(gval(n)); + } + + kp_table_unlock(t); +} + +#ifdef __KERNEL__ +static void string_convert(char *output, const char *input) +{ + if (strlen(input) > 32) { + strncpy(output, input, 32-4); + memset(output + 32-4, '.', 3); + } else + memcpy(output, input, strlen(input)); +} + +struct table_hist_record { + ktap_value key; + ktap_value val; +}; + +static int hist_record_cmp(const void *r1, const void *r2) +{ + const struct table_hist_record *i = r1; + const struct table_hist_record *j = r2; + + if ((nvalue(&i->val) == nvalue(&j->val))) { + return 0; + } else if ((nvalue(&i->val) < nvalue(&j->val))) { + return 1; + } else + return -1; +} + +static int kp_aggracc_read(ktap_aggraccval *acc); + +/* histogram: key should be number or string, value must be number */ +static void table_histdump(ktap_state *ks, ktap_table *t, int shownums) +{ + struct table_hist_record *thr; + unsigned long __maybe_unused flags; + char dist_str[40]; + int i, ratio, total = 0, count = 0, top_num, is_kernel_address = 0; + int size, num; + + size = sizeof(*thr) * (t->sizearray + sizenode(t)); + thr = kp_malloc(ks, size); + if (!thr) { + kp_error(ks, "Cannot allocate %d of histogram memory", size); + return; + } + + kp_table_lock(t); + + for (i = 0; i < t->sizearray; i++) { + ktap_value *v = &t->array[i]; + + if (isnil(v)) + continue; + + if (ttisnumber(v)) + num = nvalue(v); + else if (ttisaggracc(v)) + num = kp_aggracc_read(aggraccvalue(v)); + else { + kp_table_unlock(t); + goto error; + } + + setnvalue(&thr[count].key, i + 1); + setnvalue(&thr[count].val, num); + count++; + total += num; + } + + for (i = 0; i < sizenode(t); i++) { + ktap_tnode *n = &t->node[i]; + ktap_value *v = gval(n); + + if (isnil(gkey(n))) + continue; + + if (ttisnumber(v)) + num = nvalue(v); + else if (ttisaggracc(v)) + num = kp_aggracc_read(aggraccvalue(v)); + else { + kp_table_unlock(t); + goto error; + } + + setobj(&thr[count].key, gkey(n)); + setnvalue(&thr[count].val, num); + count++; + total += num; + } + + kp_table_unlock(t); + + sort(thr, count, sizeof(struct table_hist_record), + hist_record_cmp, NULL); + + dist_str[sizeof(dist_str) - 1] = '\0'; + + /* check the first key is a kernel text symbol or not */ + if (ttisnumber(&thr[0].key)) { + char str[KSYM_SYMBOL_LEN]; + + SPRINT_SYMBOL(str, nvalue(&thr[0].key)); + if (str[0] != '0' || str[1] != 'x') + is_kernel_address = 1; + } + + top_num = min(shownums, count); + for (i = 0; i < top_num; i++) { + ktap_value *key = &thr[i].key; + ktap_value *val = &thr[i].val; + + memset(dist_str, ' ', sizeof(dist_str) - 1); + ratio = (nvalue(val) * (sizeof(dist_str) - 1)) / total; + memset(dist_str, '@', ratio); + + if (ttisstring(key)) { + char buf[32 + 1] = {0}; + + string_convert(buf, svalue(key)); + kp_printf(ks, "%32s |%s%-7d\n", buf, dist_str, + nvalue(val)); + } else if (ttisnumber(key)) { + char str[KSYM_SYMBOL_LEN]; + char buf[32 + 1] = {0}; + + if (is_kernel_address) { + /* suppose it's a symbol, fix it in future */ + SPRINT_SYMBOL(str, nvalue(key)); + string_convert(buf, str); + kp_printf(ks, "%32s |%s%-7d\n", buf, dist_str, + nvalue(val)); + } else { + kp_printf(ks, "%32d |%s%-7d\n", nvalue(key), + dist_str, nvalue(val)); + } + } + } + + if (count > shownums) + kp_printf(ks, "%32s |\n", "..."); + + goto out; + + error: + kp_puts(ks, "error: table histogram only handle " + " (key: string/number val: number)\n"); + out: + kp_free(ks, thr); +} + +#define HISTOGRAM_DEFAULT_TOP_NUM 20 + +#define DISTRIBUTION_STR "------------- Distribution -------------" +void kp_table_histogram(ktap_state *ks, ktap_table *t) +{ + kp_printf(ks, "%32s%s%s\n", "value ", DISTRIBUTION_STR, " count"); + table_histdump(ks, t, HISTOGRAM_DEFAULT_TOP_NUM); +} + +/* + * Aggregation Table + */ + +static ktap_table *table_new2(ktap_state *ks, ktap_gcobject **list) +{ + ktap_table *t = &kp_newobject(ks, KTAP_TTABLE, sizeof(ktap_table), + list)->h; + t->flags = (u8)(~0); + t->array = NULL; + t->sizearray = 0; + t->node = (ktap_tnode *)dummynode; + t->gclist = NULL; + setnodevector(ks, t, 0); + + kp_table_lock_init(t); + return t; +} + +static int kp_aggracc_read(ktap_aggraccval *acc) +{ + switch (acc->type) { + case AGGREGATION_TYPE_COUNT: + case AGGREGATION_TYPE_MAX: + case AGGREGATION_TYPE_MIN: + case AGGREGATION_TYPE_SUM: + return acc->val; + case AGGREGATION_TYPE_AVG: + return acc->val / acc->more; + default: + return 0; + } + +} + +void kp_aggraccval_dump(ktap_state *ks, ktap_aggraccval *acc) +{ + switch (acc->type) { + case AGGREGATION_TYPE_COUNT: + case AGGREGATION_TYPE_MAX: + case AGGREGATION_TYPE_MIN: + case AGGREGATION_TYPE_SUM: + kp_printf(ks, "%d", acc->val); + break; + case AGGREGATION_TYPE_AVG: + kp_printf(ks, "%d", acc->val / acc->more); + break; + default: + break; + } +} + +static void synth_acc(ktap_aggraccval *acc1, ktap_aggraccval *acc2) +{ + switch (acc1->type) { + case AGGREGATION_TYPE_COUNT: + acc2->val += acc1->val; + break; + case AGGREGATION_TYPE_MAX: + acc2->val = max(acc1->val, acc2->val); + break; + case AGGREGATION_TYPE_MIN: + acc2->val = min(acc1->val, acc2->val); + break; + case AGGREGATION_TYPE_SUM: + acc2->val += acc1->val; + break; + case AGGREGATION_TYPE_AVG: + acc2->val += acc1->val; + acc2->more += acc1->more; + break; + default: + break; + } +} + +static ktap_aggraccval *get_accval(ktap_state *ks, int type, + ktap_gcobject **list) +{ + ktap_aggraccval *acc; + + acc = &kp_newobject(ks, KTAP_TAGGRACCVAL, sizeof(ktap_aggraccval), + list)->acc; + acc->type = type; + acc->val = 0; + acc->more = 0; + return acc; +} + +static void synth_accval(ktap_state *ks, ktap_value *o1, ktap_value *o2, + ktap_gcobject **list) +{ + ktap_aggraccval *acc; + + if (isnil(o2)) { + acc = get_accval(ks, aggraccvalue(o1)->type, list); + acc->val = aggraccvalue(o1)->val; + acc->more = aggraccvalue(o1)->more; + setaggraccvalue(o2, acc); + return; + } + + synth_acc(aggraccvalue(o1), aggraccvalue(o2)); +} + +static void move_table(ktap_state *ks, ktap_table *t1, ktap_table *t2) +{ + ktap_value *newv; + ktap_value n; + int i; + + for (i = 0; i < t1->sizearray; i++) { + ktap_value *v = &t1->array[i]; + + if (isnil(v)) + continue; + + setnvalue(&n, i); + + newv = table_set(ks, t2, &n); + synth_accval(ks, v, newv, &t2->gclist); + } + + for (i = 0; i < sizenode(t1); i++) { + ktap_tnode *node = &t1->node[i]; + + if (isnil(gkey(node))) + continue; + + newv = table_set(ks, t2, gkey(node)); + synth_accval(ks, gval(node), newv, &t2->gclist); + } +} + +ktap_table *kp_aggrtable_synthesis(ktap_state *ks, ktap_aggrtable *ah) +{ + ktap_table *synth_tbl; + int cpu; + + synth_tbl = table_new2(ks, &ah->gclist); + + for_each_possible_cpu(cpu) { + ktap_table **t = per_cpu_ptr(ah->pcpu_tbl, cpu); + move_table(ks, *t, synth_tbl); + } + + return synth_tbl; +} + +void kp_aggrtable_dump(ktap_state *ks, ktap_aggrtable *ah) +{ + kp_table_dump(ks, kp_aggrtable_synthesis(ks, ah)); +} + +ktap_aggrtable *kp_aggrtable_new(ktap_state *ks) +{ + ktap_aggrtable *ah; + int cpu; + + ah = &kp_newobject(ks, KTAP_TAGGRTABLE, sizeof(ktap_aggrtable), + NULL)->ah; + ah->pcpu_tbl = alloc_percpu(ktap_table *); + ah->gclist = NULL; + + for_each_possible_cpu(cpu) { + ktap_table **t = per_cpu_ptr(ah->pcpu_tbl, cpu); + *t = table_new2(ks, &ah->gclist); + } + + return ah; +} + +void kp_aggrtable_free(ktap_state *ks, ktap_aggrtable *ah) +{ + free_percpu(ah->pcpu_tbl); + kp_free_gclist(ks, ah->gclist); + kp_free(ks, ah); +} + +static +void handle_aggr_count(ktap_state *ks, ktap_aggrtable *ah, ktap_value *key) +{ + ktap_table *t = *__this_cpu_ptr(ah->pcpu_tbl); + ktap_value *v = table_set(ks, t, key); + ktap_aggraccval *acc; + + if (isnil(v)) { + acc = get_accval(ks, AGGREGATION_TYPE_COUNT, &t->gclist); + acc->val = 1; + setaggraccvalue(v, acc); + return; + } + + acc = aggraccvalue(v); + acc->val += 1; +} + +static +void handle_aggr_max(ktap_state *ks, ktap_aggrtable *ah, ktap_value *key) +{ + ktap_table *t = *__this_cpu_ptr(ah->pcpu_tbl); + ktap_value *v = table_set(ks, t, key); + ktap_aggraccval *acc; + + if (isnil(v)) { + acc = get_accval(ks, AGGREGATION_TYPE_MAX, &t->gclist); + acc->val = ks->aggr_accval; + setaggraccvalue(v, acc); + return; + } + + acc = aggraccvalue(v); + acc->val = max(acc->val, ks->aggr_accval); +} + +static +void handle_aggr_min(ktap_state *ks, ktap_aggrtable *ah, ktap_value *key) +{ + ktap_table *t = *__this_cpu_ptr(ah->pcpu_tbl); + ktap_value *v = table_set(ks, t, key); + ktap_aggraccval *acc; + + if (isnil(v)) { + acc = get_accval(ks, AGGREGATION_TYPE_MIN, &t->gclist); + acc->val = ks->aggr_accval; + setaggraccvalue(v, acc); + return; + } + + acc = aggraccvalue(v); + acc->val = min(acc->val, ks->aggr_accval); +} + +static +void handle_aggr_sum(ktap_state *ks, ktap_aggrtable *ah, ktap_value *key) +{ + ktap_table *t = *__this_cpu_ptr(ah->pcpu_tbl); + ktap_value *v = table_set(ks, t, key); + ktap_aggraccval *acc; + + if (isnil(v)) { + acc = get_accval(ks, AGGREGATION_TYPE_SUM, &t->gclist); + acc->val = ks->aggr_accval; + setaggraccvalue(v, acc); + return; + } + + acc = aggraccvalue(v); + acc->val += ks->aggr_accval; +} + +static +void handle_aggr_avg(ktap_state *ks, ktap_aggrtable *ah, ktap_value *key) +{ + ktap_table *t = *__this_cpu_ptr(ah->pcpu_tbl); + ktap_value *v = table_set(ks, t, key); + ktap_aggraccval *acc; + + if (isnil(v)) { + acc = get_accval(ks, AGGREGATION_TYPE_AVG, &t->gclist); + acc->val = ks->aggr_accval; + acc->more = 1; + setaggraccvalue(v, acc); + return; + } + + acc = aggraccvalue(v); + acc->val += ks->aggr_accval; + acc->more++; +} + +typedef void (*aggr_func_t)(ktap_state *ks, ktap_aggrtable *ah, ktap_value *k); +static aggr_func_t kp_aggregation_handler[] = { + handle_aggr_count, + handle_aggr_max, + handle_aggr_min, + handle_aggr_sum, + handle_aggr_avg +}; + +void kp_aggrtable_set(ktap_state *ks, ktap_aggrtable *ah, + ktap_value *key, ktap_value *val) +{ + if (unlikely(!ttisaggrval(val))) { + kp_error(ks, "set invalid value to aggregation table\n"); + return; + } + + kp_aggregation_handler[nvalue(val)](ks, ah, key); +} + + +void kp_aggrtable_get(ktap_state *ks, ktap_aggrtable *ah, ktap_value *key, + ktap_value *val) +{ + ktap_aggraccval acc; /* in stack */ + const ktap_value *v; + int cpu; + + acc.val = -1; + acc.more = -1; + + for_each_possible_cpu(cpu) { + ktap_table **t = per_cpu_ptr(ah->pcpu_tbl, cpu); + + v = table_get(*t, key); + if (isnil(v)) + continue; + + if (acc.more == -1) { + acc = *aggraccvalue(v); + continue; + } + + synth_acc(aggraccvalue(v), &acc); + } + + if (acc.more == -1) { + setnilvalue(val); + } else { + setnvalue(val, kp_aggracc_read(&acc)); + } +} + +void kp_aggrtable_histogram(ktap_state *ks, ktap_aggrtable *ah) +{ + kp_table_histogram(ks, kp_aggrtable_synthesis(ks, ah)); +} +#endif diff --git a/drivers/staging/ktap/interpreter/transport.c b/drivers/staging/ktap/interpreter/transport.c new file mode 100644 index 000000000000..4cd3662b792a --- /dev/null +++ b/drivers/staging/ktap/interpreter/transport.c @@ -0,0 +1,636 @@ +/* + * transport.c - ktap transport functionality + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <linux/debugfs.h> +#include <linux/ftrace_event.h> +#include <linux/stacktrace.h> +#include <linux/clocksource.h> +#include <asm/uaccess.h> +#include "../include/ktap.h" + +struct ktap_trace_iterator { + struct ring_buffer *buffer; + int print_timestamp; + void *private; + + struct trace_iterator iter; +}; + +enum ktap_trace_type { + __TRACE_FIRST_TYPE = 0, + + TRACE_FN = 1, /* must be same as ftrace definition in kernel */ + TRACE_PRINT, + TRACE_BPUTS, + TRACE_STACK, + TRACE_USER_STACK, + + __TRACE_LAST_TYPE, +}; + +#define KTAP_TRACE_ITER(iter) \ + container_of(iter, struct ktap_trace_iterator, iter) + +ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt) +{ + int len; + int ret; + + if (!cnt) + return 0; + + if (s->len <= s->readpos) + return -EBUSY; + + len = s->len - s->readpos; + if (cnt > len) + cnt = len; + ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt); + if (ret == cnt) + return -EFAULT; + + cnt -= ret; + + s->readpos += cnt; + return cnt; +} + +int trace_seq_puts(struct trace_seq *s, const char *str) +{ + int len = strlen(str); + + if (s->full) + return 0; + + if (len > ((PAGE_SIZE - 1) - s->len)) { + s->full = 1; + return 0; + } + + memcpy(s->buffer + s->len, str, len); + s->len += len; + + return len; +} + +static int trace_empty(struct trace_iterator *iter) +{ + struct ktap_trace_iterator *ktap_iter = KTAP_TRACE_ITER(iter); + int cpu; + + for_each_online_cpu(cpu) { + if (!ring_buffer_empty_cpu(ktap_iter->buffer, cpu)) + return 0; + } + + return 1; +} + +static void trace_consume(struct trace_iterator *iter) +{ + struct ktap_trace_iterator *ktap_iter = KTAP_TRACE_ITER(iter); + + ring_buffer_consume(ktap_iter->buffer, iter->cpu, &iter->ts, + &iter->lost_events); +} + +unsigned long long ns2usecs(cycle_t nsec) +{ + nsec += 500; + do_div(nsec, 1000); + return nsec; +} + +static int trace_print_timestamp(struct trace_iterator *iter) +{ + struct trace_seq *s = &iter->seq; + unsigned long long t; + unsigned long secs, usec_rem; + + t = ns2usecs(iter->ts); + usec_rem = do_div(t, USEC_PER_SEC); + secs = (unsigned long)t; + + return trace_seq_printf(s, "%5lu.%06lu: ", secs, usec_rem); +} + +/* todo: export kernel function ftrace_find_event in future, and make faster */ +static struct trace_event *(*ftrace_find_event)(int type); + +static enum print_line_t print_trace_fmt(struct trace_iterator *iter) +{ + struct ktap_trace_iterator *ktap_iter = KTAP_TRACE_ITER(iter); + struct trace_entry *entry = iter->ent; + struct trace_event *ev; + + ev = ftrace_find_event(entry->type); + + if (ktap_iter->print_timestamp && !trace_print_timestamp(iter)) + return TRACE_TYPE_PARTIAL_LINE; + + if (ev) { + int ret = ev->funcs->trace(iter, 0, ev); + + /* overwrite '\n' at the ending */ + iter->seq.buffer[iter->seq.len - 1] = '\0'; + iter->seq.len--; + return ret; + } + + return TRACE_TYPE_PARTIAL_LINE; +} + +static enum print_line_t print_trace_stack(struct trace_iterator *iter) +{ + struct trace_entry *entry = iter->ent; + struct stack_trace trace; + char str[KSYM_SYMBOL_LEN]; + int i; + + trace.entries = (unsigned long *)(entry + 1); + trace.nr_entries = (iter->ent_size - sizeof(*entry)) / + sizeof(unsigned long); + + if (!trace_seq_puts(&iter->seq, "<stack trace>\n")) + return TRACE_TYPE_PARTIAL_LINE; + + for (i = 0; i < trace.nr_entries; i++) { + unsigned long p = trace.entries[i]; + + if (p == ULONG_MAX) + break; + + sprint_symbol(str, p); + if (!trace_seq_printf(&iter->seq, " => %s\n", str)) + return TRACE_TYPE_PARTIAL_LINE; + } + + return TRACE_TYPE_HANDLED; +} + +struct ktap_ftrace_entry { + struct trace_entry entry; + unsigned long ip; + unsigned long parent_ip; +}; + +static enum print_line_t print_trace_fn(struct trace_iterator *iter) +{ + struct ktap_trace_iterator *ktap_iter = KTAP_TRACE_ITER(iter); + struct ktap_ftrace_entry *field = (struct ktap_ftrace_entry *)iter->ent; + char str[KSYM_SYMBOL_LEN]; + + if (ktap_iter->print_timestamp && !trace_print_timestamp(iter)) + return TRACE_TYPE_PARTIAL_LINE; + + sprint_symbol(str, field->ip); + if (!trace_seq_puts(&iter->seq, str)) + return TRACE_TYPE_PARTIAL_LINE; + + if (!trace_seq_puts(&iter->seq, " <- ")) + return TRACE_TYPE_PARTIAL_LINE; + + sprint_symbol(str, field->parent_ip); + if (!trace_seq_puts(&iter->seq, str)) + return TRACE_TYPE_PARTIAL_LINE; + + return TRACE_TYPE_HANDLED; +} + +static enum print_line_t print_trace_bputs(struct trace_iterator *iter) +{ + if (!trace_seq_puts(&iter->seq, + (const char *)(*(unsigned long *)(iter->ent + 1)))) + return TRACE_TYPE_PARTIAL_LINE; + + return TRACE_TYPE_HANDLED; +} + +static enum print_line_t print_trace_line(struct trace_iterator *iter) +{ + struct trace_entry *entry = iter->ent; + char *str = (char *)(entry + 1); + + if (entry->type == TRACE_PRINT) { + if (!trace_seq_printf(&iter->seq, "%s", str)) + return TRACE_TYPE_PARTIAL_LINE; + + return TRACE_TYPE_HANDLED; + } + + if (entry->type == TRACE_BPUTS) + return print_trace_bputs(iter); + + if (entry->type == TRACE_STACK) + return print_trace_stack(iter); + + if (entry->type == TRACE_FN) + return print_trace_fn(iter); + + return print_trace_fmt(iter); +} + +static struct trace_entry * +peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts, + unsigned long *lost_events) +{ + struct ktap_trace_iterator *ktap_iter = KTAP_TRACE_ITER(iter); + struct ring_buffer_event *event; + + event = ring_buffer_peek(ktap_iter->buffer, cpu, ts, lost_events); + if (event) { + iter->ent_size = ring_buffer_event_length(event); + return ring_buffer_event_data(event); + } + + return NULL; +} + +static struct trace_entry * +__find_next_entry(struct trace_iterator *iter, int *ent_cpu, + unsigned long *missing_events, u64 *ent_ts) +{ + struct ktap_trace_iterator *ktap_iter = KTAP_TRACE_ITER(iter); + struct ring_buffer *buffer = ktap_iter->buffer; + struct trace_entry *ent, *next = NULL; + unsigned long lost_events = 0, next_lost = 0; + u64 next_ts = 0, ts; + int next_cpu = -1; + int next_size = 0; + int cpu; + + for_each_online_cpu(cpu) { + if (ring_buffer_empty_cpu(buffer, cpu)) + continue; + + ent = peek_next_entry(iter, cpu, &ts, &lost_events); + /* + * Pick the entry with the smallest timestamp: + */ + if (ent && (!next || ts < next_ts)) { + next = ent; + next_cpu = cpu; + next_ts = ts; + next_lost = lost_events; + next_size = iter->ent_size; + } + } + + iter->ent_size = next_size; + + if (ent_cpu) + *ent_cpu = next_cpu; + + if (ent_ts) + *ent_ts = next_ts; + + if (missing_events) + *missing_events = next_lost; + + return next; +} + +/* Find the next real entry, and increment the iterator to the next entry */ +static void *trace_find_next_entry_inc(struct trace_iterator *iter) +{ + iter->ent = __find_next_entry(iter, &iter->cpu, + &iter->lost_events, &iter->ts); + if (iter->ent) + iter->idx++; + + return iter->ent ? iter : NULL; +} + +static void poll_wait_pipe(void) +{ + set_current_state(TASK_INTERRUPTIBLE); + /* sleep for 100 msecs, and try again. */ + schedule_timeout(HZ / 10); +} + +static int tracing_wait_pipe(struct file *filp) +{ + struct trace_iterator *iter = filp->private_data; + struct ktap_trace_iterator *ktap_iter = KTAP_TRACE_ITER(iter); + ktap_state *ks = ktap_iter->private; + + while (trace_empty(iter)) { + + if ((filp->f_flags & O_NONBLOCK)) { + return -EAGAIN; + } + + mutex_unlock(&iter->mutex); + + poll_wait_pipe(); + + mutex_lock(&iter->mutex); + + if (G(ks)->wait_user && trace_empty(iter)) + return -EINTR; + } + + return 1; +} + +static ssize_t +tracing_read_pipe(struct file *filp, char __user *ubuf, size_t cnt, + loff_t *ppos) +{ + struct trace_iterator *iter = filp->private_data; + ssize_t sret; + + /* return any leftover data */ + sret = trace_seq_to_user(&iter->seq, ubuf, cnt); + if (sret != -EBUSY) + return sret; + /* + * Avoid more than one consumer on a single file descriptor + * This is just a matter of traces coherency, the ring buffer itself + * is protected. + */ + mutex_lock(&iter->mutex); + +waitagain: + sret = tracing_wait_pipe(filp); + if (sret <= 0) + goto out; + + /* stop when tracing is finished */ + if (trace_empty(iter)) { + sret = 0; + goto out; + } + + if (cnt >= PAGE_SIZE) + cnt = PAGE_SIZE - 1; + + /* reset all but tr, trace, and overruns */ + memset(&iter->seq, 0, + sizeof(struct trace_iterator) - + offsetof(struct trace_iterator, seq)); + iter->pos = -1; + + while (trace_find_next_entry_inc(iter) != NULL) { + enum print_line_t ret; + int len = iter->seq.len; + + ret = print_trace_line(iter); + if (ret == TRACE_TYPE_PARTIAL_LINE) { + /* don't print partial lines */ + iter->seq.len = len; + break; + } + if (ret != TRACE_TYPE_NO_CONSUME) + trace_consume(iter); + + if (iter->seq.len >= cnt) + break; + + /* + * Setting the full flag means we reached the trace_seq buffer + * size and we should leave by partial output condition above. + * One of the trace_seq_* functions is not used properly. + */ + WARN_ONCE(iter->seq.full, "full flag set for trace type %d", + iter->ent->type); + } + + /* Now copy what we have to the user */ + sret = trace_seq_to_user(&iter->seq, ubuf, cnt); + if (iter->seq.readpos >= iter->seq.len) + trace_seq_init(&iter->seq); + + /* + * If there was nothing to send to user, in spite of consuming trace + * entries, go back to wait for more entries. + */ + if (sret == -EBUSY) + goto waitagain; + +out: + mutex_unlock(&iter->mutex); + + return sret; +} + +static int tracing_open_pipe(struct inode *inode, struct file *filp) +{ + struct ktap_trace_iterator *ktap_iter; + ktap_state *ks = inode->i_private; + + /* create a buffer to store the information to pass to userspace */ + ktap_iter = kzalloc(sizeof(*ktap_iter), GFP_KERNEL); + if (!ktap_iter) + return -ENOMEM; + + ktap_iter->private = ks; + ktap_iter->buffer = G(ks)->buffer; + ktap_iter->print_timestamp = G(ks)->parm->print_timestamp; + mutex_init(&ktap_iter->iter.mutex); + filp->private_data = &ktap_iter->iter; + + nonseekable_open(inode, filp); + + return 0; +} + +static int tracing_release_pipe(struct inode *inode, struct file *file) +{ + struct trace_iterator *iter = file->private_data; + struct ktap_trace_iterator *ktap_iter = KTAP_TRACE_ITER(iter); + + mutex_destroy(&iter->mutex); + kfree(ktap_iter); + return 0; +} + +static const struct file_operations tracing_pipe_fops = { + .open = tracing_open_pipe, + .read = tracing_read_pipe, + .splice_read = NULL, + .release = tracing_release_pipe, + .llseek = no_llseek, +}; + +/* + * print_backtrace maybe called from ktap mainthread, so be + * care on race with event closure thread. + * + * preempt disabled in ring_buffer_lock_reserve + * + * The implementation is similar with funtion __ftrace_trace_stack. + */ +void kp_transport_print_backtrace(ktap_state *ks) +{ + struct ring_buffer *buffer = G(ks)->buffer; + struct ring_buffer_event *event; + struct trace_entry *entry; + int size; + + size = KTAP_STACK_MAX_ENTRIES * sizeof(unsigned long); + event = ring_buffer_lock_reserve(buffer, sizeof(*entry) + size); + if (!event) { + return; + } else { + struct stack_trace trace; + + entry = ring_buffer_event_data(event); + tracing_generic_entry_update(entry, 0, 0); + entry->type = TRACE_STACK; + + trace.nr_entries = 0; + trace.skip = 10; + trace.max_entries = KTAP_STACK_MAX_ENTRIES; + trace.entries = (unsigned long *)(entry + 1); + save_stack_trace(&trace); + + ring_buffer_unlock_commit(buffer, event); + } + + return; +} + +void kp_transport_event_write(ktap_state *ks, struct ktap_event *e) +{ + struct ring_buffer *buffer = G(ks)->buffer; + struct ring_buffer_event *event; + struct trace_entry *entry; + + event = ring_buffer_lock_reserve(buffer, e->entry_size + + sizeof(struct ftrace_event_call *)); + if (!event) { + return; + } else { + entry = ring_buffer_event_data(event); + + memcpy(entry, e->entry, e->entry_size); + + ring_buffer_unlock_commit(buffer, event); + } +} + +void kp_transport_write(ktap_state *ks, const void *data, size_t length) +{ + struct ring_buffer *buffer = G(ks)->buffer; + struct ring_buffer_event *event; + struct trace_entry *entry; + int size; + + size = sizeof(struct trace_entry) + length; + + event = ring_buffer_lock_reserve(buffer, size); + if (!event) { + return; + } else { + entry = ring_buffer_event_data(event); + + tracing_generic_entry_update(entry, 0, 0); + entry->type = TRACE_PRINT; + memcpy(entry + 1, data, length); + + ring_buffer_unlock_commit(buffer, event); + } +} + +/* general print function */ +void kp_printf(ktap_state *ks, const char *fmt, ...) +{ + char buff[1024]; + va_list args; + int len; + + va_start(args, fmt); + len = vscnprintf(buff, 1024, fmt, args); + va_end(args); + + buff[len] = '\0'; + kp_transport_write(ks, buff, len + 1); +} + +void __kp_puts(ktap_state *ks, const char *str) +{ + kp_transport_write(ks, str, strlen(str) + 1); +} + +void __kp_bputs(ktap_state *ks, const char *str) +{ + struct ring_buffer *buffer = G(ks)->buffer; + struct ring_buffer_event *event; + struct trace_entry *entry; + int size; + + size = sizeof(struct trace_entry) + sizeof(unsigned long *); + + event = ring_buffer_lock_reserve(buffer, size); + if (!event) { + return; + } else { + entry = ring_buffer_event_data(event); + + tracing_generic_entry_update(entry, 0, 0); + entry->type = TRACE_BPUTS; + *(unsigned long *)(entry + 1) = (unsigned long)str; + + ring_buffer_unlock_commit(buffer, event); + } +} + +void kp_transport_exit(ktap_state *ks) +{ + ring_buffer_free(G(ks)->buffer); + debugfs_remove(G(ks)->trace_pipe_dentry); +} + +#define TRACE_BUF_SIZE_DEFAULT 1441792UL /* 16384 * 88 (sizeof(entry)) */ + +int kp_transport_init(ktap_state *ks, struct dentry *dir) +{ + struct ring_buffer *buffer; + struct dentry *dentry; + char filename[32] = {0}; + + ftrace_find_event = (void *)kallsyms_lookup_name("ftrace_find_event"); + if (!ftrace_find_event) { + printk("ktap: cannot lookup ftrace_find_event in kallsyms\n"); + return -EINVAL; + } + + buffer = ring_buffer_alloc(TRACE_BUF_SIZE_DEFAULT, RB_FL_OVERWRITE); + if (!buffer) + return -ENOMEM; + + sprintf(filename, "trace_pipe_%d", (int)task_tgid_vnr(current)); + + dentry = debugfs_create_file(filename, 0444, dir, + ks, &tracing_pipe_fops); + if (!dentry) { + pr_err("ktapvm: cannot create trace_pipe file in debugfs\n"); + ring_buffer_free(buffer); + return -1; + } + + G(ks)->buffer = buffer; + G(ks)->trace_pipe_dentry = dentry; + + return 0; +} + diff --git a/drivers/staging/ktap/interpreter/tstring.c b/drivers/staging/ktap/interpreter/tstring.c new file mode 100644 index 000000000000..ce4c88df2cc8 --- /dev/null +++ b/drivers/staging/ktap/interpreter/tstring.c @@ -0,0 +1,287 @@ +/* + * tstring.c - ktap tstring data struction manipulation function + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * Copyright (C) 1994-2013 Lua.org, PUC-Rio. + * - The part of code in this file is copied from lua initially. + * - lua's MIT license is compatible with GPL. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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. + */ + +#ifdef __KERNEL__ +#include "../include/ktap.h" +#else +#include "../include/ktap_types.h" +#endif + +#define STRING_MAXSHORTLEN 40 + +int kp_tstring_cmp(const ktap_string *ls, const ktap_string *rs) +{ + const char *l = getstr(ls); + size_t ll = ls->tsv.len; + const char *r = getstr(rs); + size_t lr = rs->tsv.len; + + for (;;) { + int temp = strcmp(l, r); + if (temp != 0) + return temp; + else { + /* strings are equal up to a `\0' */ + + /* index of first `\0' in both strings */ + size_t len = strlen(l); + + /* r is finished? */ + if (len == lr) + return (len == ll) ? 0 : 1; + else if (len == ll) /* l is finished? */ + return -1; + + /* + * both strings longer than `len'; + * go on comparing (after the `\0') + */ + len++; + l += len; ll -= len; r += len; lr -= len; + } + } +} + +/* + * equality for long strings + */ +int kp_tstring_eqlngstr(ktap_string *a, ktap_string *b) +{ + size_t len = a->tsv.len; + + return (a == b) || ((len == b->tsv.len) && + (memcmp(getstr(a), getstr(b), len) == 0)); +} + +/* + * equality for strings + */ +int kp_tstring_eqstr(ktap_string *a, ktap_string *b) +{ + return (a->tsv.tt == b->tsv.tt) && + (a->tsv.tt == KTAP_TSHRSTR ? eqshrstr(a, b) : + kp_tstring_eqlngstr(a, b)); +} + +#define STRING_HASHLIMIT 5 +unsigned int kp_string_hash(const char *str, size_t l, unsigned int seed) +{ + unsigned int h = seed ^ l; + size_t l1; + size_t step = (l >> STRING_HASHLIMIT) + 1; + + for (l1 = l; l1 >= step; l1 -= step) + h = h ^ ((h<<5) + (h>>2) + (u8)(str[l1 - 1])); + + return h; +} + + +/* + * resizes the string table + */ +void kp_tstring_resize(ktap_state *ks, int newsize) +{ + int i; + ktap_stringtable *tb = &G(ks)->strt; + + if (newsize > tb->size) { + kp_realloc(ks, tb->hash, tb->size, newsize, ktap_gcobject *); + + for (i = tb->size; i < newsize; i++) + tb->hash[i] = NULL; + } + + /* rehash */ + for (i = 0; i < tb->size; i++) { + ktap_gcobject *p = tb->hash[i]; + tb->hash[i] = NULL; + + while (p) { + ktap_gcobject *next = gch(p)->next; + unsigned int h = lmod(gco2ts(p)->hash, newsize); + + gch(p)->next = tb->hash[h]; + tb->hash[h] = p; + p = next; + } + } + + if (newsize < tb->size) { + /* shrinking slice must be empty */ + kp_realloc(ks, tb->hash, tb->size, newsize, ktap_gcobject *); + } + + tb->size = newsize; +} + +/* + * creates a new string object + */ +static ktap_string *createstrobj(ktap_state *ks, const char *str, size_t l, + int tag, unsigned int h, ktap_gcobject **list) +{ + ktap_string *ts; + size_t totalsize; /* total size of TString object */ + + totalsize = sizeof(ktap_string) + ((l + 1) * sizeof(char)); + ts = &kp_newobject(ks, tag, totalsize, list)->ts; + ts->tsv.len = l; + ts->tsv.hash = h; + ts->tsv.extra = 0; + memcpy(ts + 1, str, l * sizeof(char)); + ((char *)(ts + 1))[l] = '\0'; /* ending 0 */ + return ts; +} + +/* + * creates a new short string, inserting it into string table + */ +static ktap_string *newshrstr(ktap_state *ks, const char *str, size_t l, + unsigned int h) +{ + ktap_gcobject **list; + ktap_stringtable *tb = &G(ks)->strt; + ktap_string *s; + + if (tb->nuse >= (int)tb->size) + kp_tstring_resize(ks, tb->size * 2); /* too crowded */ + + list = &tb->hash[lmod(h, tb->size)]; + s = createstrobj(ks, str, l, KTAP_TSHRSTR, h, list); + tb->nuse++; + return s; +} + +#ifdef __KERNEL__ +static arch_spinlock_t tstring_lock = + (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; +#endif + +/* + * checks whether short string exists and reuses it or creates a new one + */ +static ktap_string *internshrstr(ktap_state *ks, const char *str, size_t l) +{ + ktap_gcobject *o; + ktap_global_state *g = G(ks); + ktap_string *ts; + unsigned int h = kp_string_hash(str, l, g->seed); + unsigned long __maybe_unused flags; + +#ifdef __KERNEL__ + local_irq_save(flags); + arch_spin_lock(&tstring_lock); +#endif + + for (o = g->strt.hash[lmod(h, g->strt.size)]; o != NULL; + o = gch(o)->next) { + ts = rawgco2ts(o); + + if (h == ts->tsv.hash && ts->tsv.len == l && + (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) + goto out; + } + + ts = newshrstr(ks, str, l, h); /* not found; create a new string */ + + out: +#ifdef __KERNEL__ + arch_spin_unlock(&tstring_lock); + local_irq_restore(flags); +#endif + return ts; +} + + +/* + * new string (with explicit length) + */ +ktap_string *kp_tstring_newlstr(ktap_state *ks, const char *str, size_t l) +{ + /* short string? */ + if (l <= STRING_MAXSHORTLEN) + return internshrstr(ks, str, l); + else + return createstrobj(ks, str, l, KTAP_TLNGSTR, G(ks)->seed, + NULL); +} + +ktap_string *kp_tstring_newlstr_local(ktap_state *ks, const char *str, size_t l) +{ + return createstrobj(ks, str, l, KTAP_TLNGSTR, G(ks)->seed, + &ks->gclist); +} + +/* + * new zero-terminated string + */ +ktap_string *kp_tstring_new(ktap_state *ks, const char *str) +{ + return kp_tstring_newlstr(ks, str, strlen(str)); +} + +ktap_string *kp_tstring_new_local(ktap_state *ks, const char *str) +{ + return createstrobj(ks, str, strlen(str), KTAP_TLNGSTR, G(ks)->seed, + &ks->gclist); +} + +void kp_tstring_freeall(ktap_state *ks) +{ + ktap_global_state *g = G(ks); + int h; + + for (h = 0; h < g->strt.size; h++) { + ktap_gcobject *o, *next; + o = g->strt.hash[h]; + while (o) { + next = gch(o)->next; + kp_free(ks, o); + o = next; + } + g->strt.hash[h] = NULL; + } + + kp_free(ks, g->strt.hash); +} + +/* todo: dump long string, strt table only contain short string */ +void kp_tstring_dump(ktap_state *ks) +{ + ktap_gcobject *o; + ktap_global_state *g = G(ks); + int h; + + kp_printf(ks, "tstring dump: strt size: %d, nuse: %d\n", g->strt.size, + g->strt.nuse); + for (h = 0; h < g->strt.size; h++) { + for (o = g->strt.hash[h]; o != NULL; o = gch(o)->next) { + ktap_string *ts = rawgco2ts(o); + kp_printf(ks, "%s [%d]\n", getstr(ts), (int)ts->tsv.len); + } + } +} + diff --git a/drivers/staging/ktap/interpreter/vm.c b/drivers/staging/ktap/interpreter/vm.c new file mode 100644 index 000000000000..bc7b9518a88f --- /dev/null +++ b/drivers/staging/ktap/interpreter/vm.c @@ -0,0 +1,1369 @@ +/* + * vm.c - ktap script virtual machine in Linux kernel + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * Copyright (C) 1994-2013 Lua.org, PUC-Rio. + * - The part of code in this file is copied from lua initially. + * - lua's MIT license is compatible with GPL. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <linux/slab.h> +#include <linux/ftrace_event.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include "../include/ktap.h" + +#define KTAP_MINSTACK 20 + +/* todo: enlarge maxstack for big system like 64-bit */ +#define KTAP_MAXSTACK 15000 + +#define KTAP_STACK_SIZE (BASIC_STACK_SIZE * sizeof(ktap_value)) + +#define CIST_KTAP (1 << 0) /* call is running a ktap function */ +#define CIST_REENTRY (1 << 2) + +#define isktapfunc(ci) ((ci)->callstatus & CIST_KTAP) + +static void ktap_concat(ktap_state *ks, int start, int end) +{ + int i, len = 0; + StkId top = ks->ci->u.l.base; + ktap_string *ts; + char *ptr, *buffer; + + for (i = start; i <= end; i++) { + if (!ttisstring(top + i)) { + kp_error(ks, "cannot concat non-string\n"); + setnilvalue(top + start); + return; + } + + len += rawtsvalue(top + i)->tsv.len; + } + + if (len >= KTAP_PERCPU_BUFFER_SIZE) { + kp_error(ks, "Error: too long string concatenation\n"); + return; + } + + preempt_disable_notrace(); + + buffer = kp_percpu_data(KTAP_PERCPU_DATA_BUFFER); + ptr = buffer; + + for (i = start; i <= end; i++) { + int len = rawtsvalue(top + i)->tsv.len; + strncpy(ptr, svalue(top + i), len); + ptr += len; + } + ts = kp_tstring_newlstr(ks, buffer, len); + setsvalue(top + start, ts); + + preempt_enable_notrace(); +} + +/* todo: compare l == r if both is tstring type? */ +static int lessthan(ktap_state *ks, const ktap_value *l, const ktap_value *r) +{ + if (ttisnumber(l) && ttisnumber(r)) + return NUMLT(nvalue(l), nvalue(r)); + else if (ttisstring(l) && ttisstring(r)) + return kp_tstring_cmp(rawtsvalue(l), rawtsvalue(r)) < 0; + + return 0; +} + +static int lessequal(ktap_state *ks, const ktap_value *l, const ktap_value *r) +{ + if (ttisnumber(l) && ttisnumber(r)) + return NUMLE(nvalue(l), nvalue(r)); + else if (ttisstring(l) && ttisstring(r)) + return kp_tstring_cmp(rawtsvalue(l), rawtsvalue(r)) <= 0; + + return 0; +} + +static int fb2int (int x) +{ + int e = (x >> 3) & 0x1f; + if (e == 0) + return x; + else + return ((x & 7) + 8) << (e - 1); +} + +static const ktap_value *ktap_tonumber(const ktap_value *obj, ktap_value *n) +{ + if (ttisnumber(obj)) + return obj; + + return NULL; +} + +static ktap_upval *findupval(ktap_state *ks, StkId level) +{ + ktap_global_state *g = G(ks); + ktap_gcobject **pp = &ks->openupval; + ktap_upval *p; + ktap_upval *uv; + + while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { + if (p->v == level) { /* found a corresponding upvalue? */ + return p; + } + pp = &p->next; + } + + /* not found: create a new one */ + uv = &kp_newobject(ks, KTAP_TUPVAL, sizeof(ktap_upval), pp)->uv; + uv->v = level; /* current value lives in the stack */ + uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ + uv->u.l.next = g->uvhead.u.l.next; + uv->u.l.next->u.l.prev = uv; + g->uvhead.u.l.next = uv; + return uv; +} + +/* todo: implement this*/ +static void function_close (ktap_state *ks, StkId level) +{ +} + +/* create a new closure */ +static void pushclosure(ktap_state *ks, ktap_proto *p, ktap_upval **encup, + StkId base, StkId ra) +{ + int nup = p->sizeupvalues; + ktap_upvaldesc *uv = p->upvalues; + int i; + ktap_closure *ncl = kp_newlclosure(ks, nup); + + ncl->l.p = p; + setcllvalue(ra, ncl); /* anchor new closure in stack */ + + /* fill in its upvalues */ + for (i = 0; i < nup; i++) { + if (uv[i].instack) { + /* upvalue refers to local variable? */ + ncl->l.upvals[i] = findupval(ks, base + uv[i].idx); + } else { + /* get upvalue from enclosing function */ + ncl->l.upvals[i] = encup[uv[i].idx]; + } + } + //p->cache = ncl; /* save it on cache for reuse */ +} + +static void gettable(ktap_state *ks, const ktap_value *t, ktap_value *key, + StkId val) +{ + if (ttistable(t)) { + setobj(val, kp_table_get(hvalue(t), key)); + } else if (ttisaggrtable(t)) { + kp_aggrtable_get(ks, ahvalue(t), key, val); + } else { + kp_error(ks, "get key from non-table\n"); + } +} + +static void settable(ktap_state *ks, const ktap_value *t, ktap_value *key, + StkId val) +{ + if (ttistable(t)) { + kp_table_setvalue(ks, hvalue(t), key, val); + } else if (ttisaggrtable(t)) { + kp_aggrtable_set(ks, ahvalue(t), key, val); + } else { + kp_error(ks, "set key to non-table\n"); + } +} + +static void settable_incr(ktap_state *ks, const ktap_value *t, ktap_value *key, + StkId val) +{ + if (unlikely(!ttistable(t))) { + kp_error(ks, "use += operator for non-table\n"); + return; + } + + if (unlikely(!ttisnumber(val))) { + kp_error(ks, "use non-number to += operator\n"); + return; + } + + kp_table_atomic_inc(ks, hvalue(t), key, nvalue(val)); +} + + +static void growstack(ktap_state *ks, int n) +{ + ktap_value *oldstack; + int lim; + ktap_callinfo *ci; + ktap_gcobject *up; + int size = ks->stacksize; + int needed = (int)(ks->top - ks->stack) + n; + int newsize = 2 * size; + + if (newsize > KTAP_MAXSTACK) + newsize = KTAP_MAXSTACK; + + if (newsize < needed) + newsize = needed; + + if (newsize > KTAP_MAXSTACK) { /* stack overflow? */ + kp_error(ks, "stack overflow\n"); + return; + } + + /* realloc stack */ + oldstack = ks->stack; + lim = ks->stacksize; + kp_realloc(ks, ks->stack, ks->stacksize, newsize, ktap_value); + + for (; lim < newsize; lim++) + setnilvalue(ks->stack + lim); + ks->stacksize = newsize; + ks->stack_last = ks->stack + newsize; + + /* correct stack */ + ks->top = (ks->top - oldstack) + ks->stack; + for (up = ks->openupval; up != NULL; up = up->gch.next) + gco2uv(up)->v = (gco2uv(up)->v - oldstack) + ks->stack; + + for (ci = ks->ci; ci != NULL; ci = ci->prev) { + ci->top = (ci->top - oldstack) + ks->stack; + ci->func = (ci->func - oldstack) + ks->stack; + if (isktapfunc(ci)) + ci->u.l.base = (ci->u.l.base - oldstack) + ks->stack; + } + +} + +static inline void checkstack(ktap_state *ks, int n) +{ + if (ks->stack_last - ks->top <= n) + growstack(ks, n); +} + +static StkId adjust_varargs(ktap_state *ks, ktap_proto *p, int actual) +{ + int i; + int nfixargs = p->numparams; + StkId base, fixed; + + /* move fixed parameters to final position */ + fixed = ks->top - actual; /* first fixed argument */ + base = ks->top; /* final position of first argument */ + + for (i=0; i < nfixargs; i++) { + setobj(ks->top++, fixed + i); + setnilvalue(fixed + i); + } + + return base; +} + +static int poscall(ktap_state *ks, StkId first_result) +{ + ktap_callinfo *ci; + StkId res; + int wanted, i; + + ci = ks->ci; + + res = ci->func; + wanted = ci->nresults; + + ks->ci = ci = ci->prev; + + for (i = wanted; i != 0 && first_result < ks->top; i--) + setobj(res++, first_result++); + + while(i-- > 0) + setnilvalue(res++); + + ks->top = res; + + return (wanted - (-1)); +} + +static ktap_callinfo *extend_ci(ktap_state *ks) +{ + ktap_callinfo *ci; + + ci = kp_malloc(ks, sizeof(ktap_callinfo)); + ks->ci->next = ci; + ci->prev = ks->ci; + ci->next = NULL; + + return ci; +} + +static void free_ci(ktap_state *ks) +{ + ktap_callinfo *ci = ks->ci; + ktap_callinfo *next; + + if (!ci) + return; + + next = ci->next; + ci->next = NULL; + while ((ci = next) != NULL) { + next = ci->next; + kp_free(ks, ci); + } +} + +#define next_ci(ks) (ks->ci = ks->ci->next ? ks->ci->next : extend_ci(ks)) +#define savestack(ks, p) ((char *)(p) - (char *)ks->stack) +#define restorestack(ks, n) ((ktap_value *)((char *)ks->stack + (n))) + +static int precall(ktap_state *ks, StkId func, int nresults) +{ + ktap_cfunction f; + ktap_callinfo *ci; + ktap_proto *p; + StkId base; + ptrdiff_t funcr = savestack(ks, func); + int n; + + switch (ttype(func)) { + case KTAP_TLCF: /* light C function */ + f = fvalue(func); + goto CFUNC; + case KTAP_TCCL: /* C closure */ + f = clcvalue(func)->f; + CFUNC: + checkstack(ks, KTAP_MINSTACK); + ci = next_ci(ks); + ci->nresults = nresults; + ci->func = restorestack(ks, funcr); + ci->top = ks->top + KTAP_MINSTACK; + ci->callstatus = 0; + n = (*f)(ks); + poscall(ks, ks->top - n); + return 1; + case KTAP_TLCL: + p = CLVALUE(func)->p; + checkstack(ks, p->maxstacksize); + func = restorestack(ks, funcr); + n = (int)(ks->top - func) - 1; /* number of real arguments */ + + /* complete missing arguments */ + for (; n < p->numparams; n++) + setnilvalue(ks->top++); + + base = (!p->is_vararg) ? func + 1 : adjust_varargs(ks, p, n); + ci = next_ci(ks); + ci->nresults = nresults; + ci->func = func; + ci->u.l.base = base; + ci->top = base + p->maxstacksize; + ci->u.l.savedpc = p->code; /* starting point */ + ci->callstatus = CIST_KTAP; + ks->top = ci->top; + return 0; + default: + kp_error(ks, "attempt to call nil function\n"); + } + + return 0; +} + +#define RA(i) (base+GETARG_A(i)) +#define RB(i) (base+GETARG_B(i)) +#define ISK(x) ((x) & BITRK) +#define RC(i) base+GETARG_C(i) +#define RKB(i) \ + ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i) +#define RKC(i) \ + ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i) + +#define dojump(ci,i,e) { \ + ci->u.l.savedpc += GETARG_sBx(i) + e; } +#define donextjump(ci) { instr = *ci->u.l.savedpc; dojump(ci, instr, 1); } + +#define arith_op(ks, op) { \ + ktap_value *rb = RKB(instr); \ + ktap_value *rc = RKC(instr); \ + if (ttisnumber(rb) && ttisnumber(rc)) { \ + ktap_number nb = nvalue(rb), nc = nvalue(rc); \ + setnvalue(ra, op(nb, nc)); \ + } else { \ + kp_puts(ks, "Error: Cannot make arith operation\n"); \ + return; \ + } } + +static ktap_value *cfunction_cache_get(ktap_state *ks, int index); + +static void ktap_execute(ktap_state *ks) +{ + int exec_count = 0; + ktap_callinfo *ci; + ktap_lclosure *cl; + ktap_value *k; + unsigned int instr, opcode; + StkId base; /* stack pointer */ + StkId ra; /* register pointer */ + int res, nresults; /* temp varible */ + + ci = ks->ci; + + newframe: + cl = CLVALUE(ci->func); + k = cl->p->k; + base = ci->u.l.base; + + mainloop: + /* main loop of interpreter */ + + /* dead loop detaction */ + if (exec_count++ == kp_max_exec_count) { + if (G(ks)->mainthread != ks) { + kp_error(ks, "non-mainthread executed instructions " + "exceed max limit(%d)\n", + kp_max_exec_count); + return; + } + + cond_resched(); + if (signal_pending(current)) { + flush_signals(current); + return; + } + exec_count = 0; + } + + instr = *(ci->u.l.savedpc++); + opcode = GET_OPCODE(instr); + + /* ra is target register */ + ra = RA(instr); + + switch (opcode) { + case OP_MOVE: + setobj(ra, base + GETARG_B(instr)); + break; + case OP_LOADK: + setobj(ra, k + GETARG_Bx(instr)); + break; + case OP_LOADKX: + setobj(ra, k + GETARG_Ax(*ci->u.l.savedpc++)); + break; + case OP_LOADBOOL: + setbvalue(ra, GETARG_B(instr)); + if (GETARG_C(instr)) + ci->u.l.savedpc++; + break; + case OP_LOADNIL: { + int b = GETARG_B(instr); + do { + setnilvalue(ra++); + } while (b--); + break; + } + case OP_GETUPVAL: { + int b = GETARG_B(instr); + setobj(ra, cl->upvals[b]->v); + break; + } + case OP_GETTABUP: { + int b = GETARG_B(instr); + gettable(ks, cl->upvals[b]->v, RKC(instr), ra); + base = ci->u.l.base; + break; + } + case OP_GETTABLE: + gettable(ks, RB(instr), RKC(instr), ra); + base = ci->u.l.base; + break; + case OP_SETTABUP: { + int a = GETARG_A(instr); + settable(ks, cl->upvals[a]->v, RKB(instr), RKC(instr)); + base = ci->u.l.base; + break; + } + case OP_SETTABUP_INCR: { + int a = GETARG_A(instr); + settable_incr(ks, cl->upvals[a]->v, RKB(instr), RKC(instr)); + base = ci->u.l.base; + break; + } + case OP_SETUPVAL: { + ktap_upval *uv = cl->upvals[GETARG_B(instr)]; + setobj(uv->v, ra); + break; + } + case OP_SETTABLE: + settable(ks, ra, RKB(instr), RKC(instr)); + base = ci->u.l.base; + break; + case OP_SETTABLE_INCR: + settable_incr(ks, ra, RKB(instr), RKC(instr)); + base = ci->u.l.base; + break; + case OP_NEWTABLE: { + int b = GETARG_B(instr); + int c = GETARG_C(instr); + ktap_table *t = kp_table_new(ks); + sethvalue(ra, t); + if (b != 0 || c != 0) + kp_table_resize(ks, t, fb2int(b), fb2int(c)); + break; + } + case OP_SELF: { + StkId rb = RB(instr); + setobj(ra+1, rb); + gettable(ks, rb, RKC(instr), ra); + base = ci->u.l.base; + break; + } + case OP_ADD: + arith_op(ks, NUMADD); + break; + case OP_SUB: + arith_op(ks, NUMSUB); + break; + case OP_MUL: + arith_op(ks, NUMMUL); + break; + case OP_DIV: + /* divide 0 checking */ + if (!nvalue(RKC(instr))) { + kp_error(ks, "divide 0 arith operation\n"); + return; + } + arith_op(ks, NUMDIV); + break; + case OP_MOD: + /* divide 0 checking */ + if (!nvalue(RKC(instr))) { + kp_error(ks, "mod 0 arith operation\n"); + return; + } + arith_op(ks, NUMMOD); + break; + case OP_POW: + kp_error(ks, "ktap don't support pow arith in kernel\n"); + return; + case OP_UNM: { + ktap_value *rb = RB(instr); + if (ttisnumber(rb)) { + ktap_number nb = nvalue(rb); + setnvalue(ra, NUMUNM(nb)); + } + break; + } + case OP_NOT: + res = isfalse(RB(instr)); + setbvalue(ra, res); + break; + case OP_LEN: { + int len = kp_objlen(ks, RB(instr)); + if (len < 0) + return; + setnvalue(ra, len); + break; + } + case OP_CONCAT: { + int b = GETARG_B(instr); + int c = GETARG_C(instr); + ktap_concat(ks, b, c); + break; + } + case OP_JMP: + dojump(ci, instr, 0); + break; + case OP_EQ: { + ktap_value *rb = RKB(instr); + ktap_value *rc = RKC(instr); + if ((int)equalobj(ks, rb, rc) != GETARG_A(instr)) + ci->u.l.savedpc++; + else + donextjump(ci); + + base = ci->u.l.base; + break; + } + case OP_LT: + if (lessthan(ks, RKB(instr), RKC(instr)) != GETARG_A(instr)) + ci->u.l.savedpc++; + else + donextjump(ci); + base = ci->u.l.base; + break; + case OP_LE: + if (lessequal(ks, RKB(instr), RKC(instr)) != GETARG_A(instr)) + ci->u.l.savedpc++; + else + donextjump(ci); + base = ci->u.l.base; + break; + case OP_TEST: + if (GETARG_C(instr) ? isfalse(ra) : !isfalse(ra)) + ci->u.l.savedpc++; + else + donextjump(ci); + break; + case OP_TESTSET: { + ktap_value *rb = RB(instr); + if (GETARG_C(instr) ? isfalse(rb) : !isfalse(rb)) + ci->u.l.savedpc++; + else { + setobj(ra, rb); + donextjump(ci); + } + break; + } + case OP_CALL: { + int b = GETARG_B(instr); + int ret; + + nresults = GETARG_C(instr) - 1; + + if (b != 0) + ks->top = ra + b; + + ret = precall(ks, ra, nresults); + if (ret) { /* C function */ + if (nresults >= 0) + ks->top = ci->top; + base = ci->u.l.base; + break; + } else { /* ktap function */ + ci = ks->ci; + /* this flag is used for return time, see OP_RETURN */ + ci->callstatus |= CIST_REENTRY; + goto newframe; + } + break; + } + case OP_TAILCALL: { + int b = GETARG_B(instr); + + if (b != 0) + ks->top = ra+b; + if (precall(ks, ra, -1)) /* C function? */ + base = ci->u.l.base; + else { + int aux; + + /* + * tail call: put called frame (n) in place of + * caller one (o) + */ + ktap_callinfo *nci = ks->ci; /* called frame */ + ktap_callinfo *oci = nci->prev; /* caller frame */ + StkId nfunc = nci->func; /* called function */ + StkId ofunc = oci->func; /* caller function */ + /* last stack slot filled by 'precall' */ + StkId lim = nci->u.l.base + + CLVALUE(nfunc)->p->numparams; + + /* close all upvalues from previous call */ + if (cl->p->sizep > 0) + function_close(ks, oci->u.l.base); + + /* move new frame into old one */ + for (aux = 0; nfunc + aux < lim; aux++) + setobj(ofunc + aux, nfunc + aux); + /* correct base */ + oci->u.l.base = ofunc + (nci->u.l.base - nfunc); + /* correct top */ + oci->top = ks->top = ofunc + (ks->top - nfunc); + oci->u.l.savedpc = nci->u.l.savedpc; + /* remove new frame */ + ci = ks->ci = oci; + /* restart ktap_execute over new ktap function */ + goto newframe; + } + break; + } + case OP_RETURN: { + int b = GETARG_B(instr); + if (b != 0) + ks->top = ra+b-1; + if (cl->p->sizep > 0) + function_close(ks, base); + b = poscall(ks, ra); + + /* if it's called from external invocation, just return */ + if (!(ci->callstatus & CIST_REENTRY)) + return; + + ci = ks->ci; + if (b) + ks->top = ci->top; + goto newframe; + } + case OP_FORLOOP: { + ktap_number step = nvalue(ra+2); + /* increment index */ + ktap_number idx = NUMADD(nvalue(ra), step); + ktap_number limit = nvalue(ra+1); + if (NUMLT(0, step) ? NUMLE(idx, limit) : NUMLE(limit, idx)) { + ci->u.l.savedpc += GETARG_sBx(instr); /* jump back */ + setnvalue(ra, idx); /* update internal index... */ + setnvalue(ra+3, idx); /* ...and external index */ + } + break; + } + case OP_FORPREP: { + const ktap_value *init = ra; + const ktap_value *plimit = ra + 1; + const ktap_value *pstep = ra + 2; + + if (!ktap_tonumber(init, ra)) { + kp_error(ks, KTAP_QL("for") + " initial value must be a number\n"); + return; + } else if (!ktap_tonumber(plimit, ra + 1)) { + kp_error(ks, KTAP_QL("for") + " limit must be a number\n"); + return; + } else if (!ktap_tonumber(pstep, ra + 2)) { + kp_error(ks, KTAP_QL("for") " step must be a number\n"); + return; + } + + setnvalue(ra, NUMSUB(nvalue(ra), nvalue(pstep))); + ci->u.l.savedpc += GETARG_sBx(instr); + break; + } + case OP_TFORCALL: { + StkId cb = ra + 3; /* call base */ + setobj(cb + 2, ra + 2); + setobj(cb + 1, ra + 1); + setobj(cb, ra); + ks->top = cb + 3; /* func. + 2 args (state and index) */ + kp_call(ks, cb, GETARG_C(instr)); + base = ci->u.l.base; + ks->top = ci->top; + instr = *(ci->u.l.savedpc++); /* go to next instruction */ + ra = RA(instr); + } + /*go through */ + case OP_TFORLOOP: + if (!ttisnil(ra + 1)) { /* continue loop? */ + setobj(ra, ra + 1); /* save control variable */ + ci->u.l.savedpc += GETARG_sBx(instr); /* jump back */ + } + break; + case OP_SETLIST: { + int n = GETARG_B(instr); + int c = GETARG_C(instr); + int last; + ktap_table *h; + + if (n == 0) + n = (int)(ks->top - ra) - 1; + if (c == 0) + c = GETARG_Ax(*ci->u.l.savedpc++); + + h = hvalue(ra); + last = ((c - 1) * LFIELDS_PER_FLUSH) + n; + if (last > h->sizearray) /* needs more space? */ + kp_table_resizearray(ks, h, last); + + for (; n > 0; n--) { + ktap_value *val = ra+n; + kp_table_setint(ks, h, last--, val); + } + /* correct top (in case of previous open call) */ + ks->top = ci->top; + break; + } + case OP_CLOSURE: { + /* need to use closure cache? (multithread contention issue)*/ + ktap_proto *p = cl->p->p[GETARG_Bx(instr)]; + pushclosure(ks, p, cl->upvals, base, ra); + break; + } + case OP_VARARG: { + int b = GETARG_B(instr) - 1; + int j; + int n = (int)(base - ci->func) - cl->p->numparams - 1; + if (b < 0) { /* B == 0? */ + b = n; /* get all var. arguments */ + checkstack(ks, n); + /* previous call may change the stack */ + ra = RA(instr); + ks->top = ra + n; + } + for (j = 0; j < b; j++) { + if (j < n) { + setobj(ra + j, base - n + j); + } else + setnilvalue(ra + j); + } + break; + } + case OP_EXTRAARG: + return; + + case OP_EVENT: { + struct ktap_event *e = ks->current_event; + + if (unlikely(!e)) { + kp_error(ks, "invalid event context\n"); + return; + } + setevalue(ra, e); + break; + } + + case OP_EVENTNAME: { + struct ktap_event *e = ks->current_event; + + if (unlikely(!e)) { + kp_error(ks, "invalid event context\n"); + return; + } + setsvalue(ra, kp_tstring_new(ks, e->call->name)); + break; + } + case OP_EVENTARG: + if (unlikely(!ks->current_event)) { + kp_error(ks, "invalid event context\n"); + return; + } + + kp_event_getarg(ks, ra, GETARG_B(instr)); + break; + case OP_LOAD_GLOBAL: { + ktap_value *cfunc = cfunction_cache_get(ks, GETARG_C(instr)); + setobj(ra, cfunc); + } + break; + + case OP_EXIT: + return; + } + + goto mainloop; +} + +void kp_call(ktap_state *ks, StkId func, int nresults) +{ + if (!precall(ks, func, nresults)) + ktap_execute(ks); +} + +static int cfunction_cache_getindex(ktap_state *ks, ktap_value *fname); + +/* + * This function must be called before all code loaded. + */ +void kp_optimize_code(ktap_state *ks, int level, ktap_proto *f) +{ + int i; + + for (i = 0; i < f->sizecode; i++) { + int instr = f->code[i]; + ktap_value *k = f->k; + + if (GET_OPCODE(instr) == OP_GETTABUP) { + if ((GETARG_B(instr) == 0) && ISK(GETARG_C(instr))) { + ktap_value *field = k + INDEXK(GETARG_C(instr)); + if (ttype(field) == KTAP_TSTRING) { + int index = cfunction_cache_getindex(ks, + field); + if (index == -1) + break; + + SET_OPCODE(instr, OP_LOAD_GLOBAL); + SETARG_C(instr, index); + f->code[i] = instr; + break; + } + } + } + } + + /* continue optimize sub functions */ + for (i = 0; i < f->sizep; i++) + kp_optimize_code(ks, level + 1, f->p[i]); +} + +static ktap_value *cfunction_cache_get(ktap_state *ks, int index) +{ + return &G(ks)->cfunction_tbl[index]; +} + +static int cfunction_cache_getindex(ktap_state *ks, ktap_value *fname) +{ + const ktap_value *gt = kp_table_getint(hvalue(&G(ks)->registry), + KTAP_RIDX_GLOBALS); + const ktap_value *cfunc; + int nr, i; + + nr = G(ks)->nr_builtin_cfunction; + cfunc = kp_table_get(hvalue(gt), fname); + + for (i = 0; i < nr; i++) { + if (rawequalobj(&G(ks)->cfunction_tbl[i], cfunc)) + return i; + } + + return -1; +} + +static void cfunction_cache_add(ktap_state *ks, ktap_value *func) +{ + int nr = G(ks)->nr_builtin_cfunction; + setobj(&G(ks)->cfunction_tbl[nr], func); + G(ks)->nr_builtin_cfunction++; +} + +static void cfunction_cache_exit(ktap_state *ks) +{ + kp_free(ks, G(ks)->cfunction_tbl); +} + +static int cfunction_cache_init(ktap_state *ks) +{ + G(ks)->cfunction_tbl = kp_zalloc(ks, sizeof(ktap_value) * 128); + if (!G(ks)->cfunction_tbl) + return -ENOMEM; + + return 0; +} + +/* function for register library */ +void kp_register_lib(ktap_state *ks, const char *libname, const ktap_Reg *funcs) +{ + int i; + ktap_table *target_tbl; + const ktap_value *gt = kp_table_getint(hvalue(&G(ks)->registry), + KTAP_RIDX_GLOBALS); + + /* lib is null when register baselib function */ + if (libname == NULL) + target_tbl = hvalue(gt); + else { + ktap_value key, val; + + target_tbl = kp_table_new(ks); + kp_table_resize(ks, target_tbl, 0, + sizeof(*funcs) / sizeof(ktap_Reg)); + + setsvalue(&key, kp_tstring_new(ks, libname)); + sethvalue(&val, target_tbl); + kp_table_setvalue(ks, hvalue(gt), &key, &val); + } + + for (i = 0; funcs[i].name != NULL; i++) { + ktap_value func_name, cl; + + setsvalue(&func_name, kp_tstring_new(ks, funcs[i].name)); + setfvalue(&cl, funcs[i].func); + kp_table_setvalue(ks, target_tbl, &func_name, &cl); + + cfunction_cache_add(ks, &cl); + } +} + +#define BASIC_STACK_SIZE (2 * KTAP_MINSTACK) + +static void kp_init_registry(ktap_state *ks) +{ + ktap_value mt; + ktap_table *registry = kp_table_new(ks); + + sethvalue(&G(ks)->registry, registry); + kp_table_resize(ks, registry, KTAP_RIDX_LAST, 0); + setthvalue(ks, &mt, ks); + kp_table_setint(ks, registry, KTAP_RIDX_MAINTHREAD, &mt); + sethvalue(&mt, kp_table_new(ks)); + kp_table_setint(ks, registry, KTAP_RIDX_GLOBALS, &mt); +} + +static int kp_init_arguments(ktap_state *ks, int argc, char __user **user_argv) +{ + const ktap_value *gt = kp_table_getint(hvalue(&G(ks)->registry), + KTAP_RIDX_GLOBALS); + ktap_table *global_tbl = hvalue(gt); + ktap_table *arg_tbl = kp_table_new(ks); + ktap_value arg_tblval; + ktap_value arg_tsval; + char **argv; + int i, ret; + + setsvalue(&arg_tsval, kp_tstring_new(ks, "arg")); + sethvalue(&arg_tblval, arg_tbl); + kp_table_setvalue(ks, global_tbl, &arg_tsval, &arg_tblval); + + if (!argc) + return 0; + + if (argc > 1024) + return -EINVAL; + + argv = kzalloc(argc * sizeof(char *), GFP_KERNEL); + if (!argv) + return -ENOMEM; + + ret = copy_from_user(argv, user_argv, argc * sizeof(char *)); + if (ret < 0) { + kfree(argv); + return -EFAULT; + } + + kp_table_resize(ks, arg_tbl, argc, 1); + + ret = 0; + for (i = 0; i < argc; i++) { + ktap_value val; + char __user *ustr = argv[i]; + char * kstr; + int len; + int res; + + len = strlen_user(ustr); + if (len > 0x1000) { + ret = -EINVAL; + break; + } + + kstr = kmalloc(len + 1, GFP_KERNEL); + if (!kstr) { + ret = -ENOMEM; + break; + } + + if (strncpy_from_user(kstr, ustr, len) < 0) { + ret = -EFAULT; + break; + } + + kstr[len] = '\0'; + + if (!kstrtoint(kstr, 10, &res)) { + setnvalue(&val, res); + } else + setsvalue(&val, kp_tstring_new(ks, kstr)); + + kp_table_setint(ks, arg_tbl, i, &val); + + kfree(kstr); + } + + kfree(argv); + return ret; +} + +DEFINE_PER_CPU(int, kp_recursion_context[PERF_NR_CONTEXTS]); + +/* todo: make this per-session aware */ +static void __percpu *kp_pcpu_data[KTAP_PERCPU_DATA_MAX][PERF_NR_CONTEXTS]; + +void *kp_percpu_data(int type) +{ + return this_cpu_ptr(kp_pcpu_data[type][trace_get_context_bit()]); +} + +static void free_kp_percpu_data(void) +{ + int i, j; + + for (i = 0; i < KTAP_PERCPU_DATA_MAX; i++) { + for (j = 0; j < PERF_NR_CONTEXTS; j++) { + free_percpu(kp_pcpu_data[i][j]); + kp_pcpu_data[i][j] = NULL; + } + } +} + +static int alloc_kp_percpu_data(void) +{ + int data_size[KTAP_PERCPU_DATA_MAX] = { + sizeof(ktap_state), KTAP_STACK_SIZE, KTAP_PERCPU_BUFFER_SIZE, + KTAP_PERCPU_BUFFER_SIZE, sizeof(ktap_btrace)}; + int i, j; + + for (i = 0; i < KTAP_PERCPU_DATA_MAX; i++) { + for (j = 0; j < PERF_NR_CONTEXTS; j++) { + void __percpu *data = __alloc_percpu(data_size[i], + __alignof__(char)); + if (!data) + goto fail; + kp_pcpu_data[i][j] = data; + } + } + + return 0; + + fail: + free_kp_percpu_data(); + return -ENOMEM; +} + +static void kp_init_state(ktap_state *ks) +{ + ktap_callinfo *ci; + int i; + + ks->stacksize = BASIC_STACK_SIZE; + + for (i = 0; i < BASIC_STACK_SIZE; i++) + setnilvalue(ks->stack + i); + + ks->top = ks->stack; + ks->stack_last = ks->stack + ks->stacksize; + + ci = &ks->baseci; + ci->callstatus = 0; + ci->func = ks->top; + setnilvalue(ks->top++); + ci->top = ks->top + KTAP_MINSTACK; + ks->ci = ci; +} + +static void free_all_ci(ktap_state *ks) +{ + int cpu; + + for_each_possible_cpu(cpu) { + ktap_state *ks; + int j; + + for (j = 0; j < PERF_NR_CONTEXTS; j++) { + if (!kp_pcpu_data[KTAP_PERCPU_DATA_STATE][j]) + break; + + ks = per_cpu_ptr(kp_pcpu_data[KTAP_PERCPU_DATA_STATE][j], cpu); + if (!ks) + break; + + free_ci(ks); + } + } + + free_ci(ks); +} + +void kp_exitthread(ktap_state *ks) +{ + /* free local allocation objects, like annotate strings */ + kp_free_gclist(ks, ks->gclist); +} + +ktap_state *kp_newthread(ktap_state *mainthread) +{ + ktap_state *ks; + + ks = kp_percpu_data(KTAP_PERCPU_DATA_STATE); + ks->stack = kp_percpu_data(KTAP_PERCPU_DATA_STACK); + G(ks) = G(mainthread); + ks->gclist = NULL; + kp_init_state(ks); + return ks; +} + +/* + * wait ktapio thread read all content in ring buffer. + * + * Here we use stupid approach to sync with ktapio thread, + * note that we cannot use semaphore/completion/other sync method, + * because ktapio thread could be killed by SIG_KILL in anytime, there + * have no safe way to up semaphore or wake waitqueue before thread exit. + * + * we also cannot use waitqueue of current->signal->wait_chldexit to sync + * exit, becasue mainthread and ktapio thread are in same thread group. + * + * Also ktap mainthread must wait ktapio thread exit, otherwise ktapio + * thread will oops when access ktap structure. + */ +static void wait_user_completion(ktap_state *ks) +{ + struct task_struct *tsk = G(ks)->task; + G(ks)->wait_user = 1; + + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + /* sleep for 100 msecs, and try again. */ + schedule_timeout(HZ / 10); + + if (get_nr_threads(tsk) == 1) + break; + } +} + +/* kp_wait: used for mainthread waiting for exit */ +static void kp_wait(ktap_state *ks) +{ + struct task_struct *task = G(ks)->trace_task; + + if (G(ks)->exit) + return; + + ks->stop = 0; + + /* tell workload process to start executing */ + if (G(ks)->parm->workload) + send_sig(SIGINT, G(ks)->trace_task, 0); + + while (!ks->stop) { + set_current_state(TASK_INTERRUPTIBLE); + /* sleep for 100 msecs, and try again. */ + schedule_timeout(HZ / 10); + + if (signal_pending(current)) { + flush_signals(current); + + /* newline for handle CTRL+C display as ^C */ + kp_puts(ks, "\n"); + break; + } + + /* stop waiting if target pid is exited */ + if (task && task->state == TASK_DEAD) + break; + } + +} + +void kp_exit(ktap_state *ks) +{ + set_next_as_exit(ks); + + G(ks)->mainthread->stop = 1; + G(ks)->exit = 1; +} + +void kp_final_exit(ktap_state *ks) +{ + if (!list_empty(&G(ks)->probe_events_head) || + !list_empty(&G(ks)->timers)) + kp_wait(ks); + + if (G(ks)->trace_task) + put_task_struct(G(ks)->trace_task); + + kp_exit_timers(ks); + kp_probe_exit(ks); + + /* free all resources got by ktap */ + kp_tstring_freeall(ks); + kp_free_all_gcobject(ks); + cfunction_cache_exit(ks); + + wait_user_completion(ks); + + kp_transport_exit(ks); + + kp_exitthread(ks); + kp_free(ks, ks->stack); + free_all_ci(ks); + + free_kp_percpu_data(); + + free_cpumask_var(G(ks)->cpumask); + kp_free(ks, ks); +} + +/* ktap mainthread initization, main entry for ktap */ +ktap_state *kp_newstate(ktap_parm *parm, struct dentry *dir) +{ + ktap_state *ks; + pid_t pid; + int cpu; + + ks = kzalloc(sizeof(ktap_state) + sizeof(ktap_global_state), + GFP_KERNEL); + if (!ks) + return NULL; + + ks->stack = kp_malloc(ks, KTAP_STACK_SIZE); + G(ks) = (ktap_global_state *)(ks + 1); + G(ks)->mainthread = ks; + G(ks)->seed = 201236; /* todo: make more random in future */ + G(ks)->task = current; + G(ks)->parm = parm; + INIT_LIST_HEAD(&(G(ks)->timers)); + INIT_LIST_HEAD(&(G(ks)->probe_events_head)); + G(ks)->exit = 0; + + if (kp_transport_init(ks, dir)) + goto out; + + pid = (pid_t)parm->trace_pid; + if (pid != -1) { + struct task_struct *task; + + rcu_read_lock(); + task = pid_task(find_vpid(pid), PIDTYPE_PID); + if (!task) { + kp_error(ks, "cannot find pid %d\n", pid); + rcu_read_unlock(); + goto out; + } + G(ks)->trace_task = task; + get_task_struct(task); + rcu_read_unlock(); + } + + if( !alloc_cpumask_var(&G(ks)->cpumask, GFP_KERNEL)) + goto out; + + cpumask_copy(G(ks)->cpumask, cpu_online_mask); + + cpu = parm->trace_cpu; + if (cpu != -1) { + if (!cpu_online(cpu)) { + printk(KERN_INFO "ktap: cpu %d is not online\n", cpu); + goto out; + } + + cpumask_clear(G(ks)->cpumask); + cpumask_set_cpu(cpu, G(ks)->cpumask); + } + + if (cfunction_cache_init(ks)) + goto out; + + kp_tstring_resize(ks, 512); /* set inital string hashtable size */ + + kp_init_state(ks); + kp_init_registry(ks); + kp_init_arguments(ks, parm->argc, parm->argv); + + /* init library */ + kp_init_baselib(ks); + kp_init_kdebuglib(ks); + kp_init_timerlib(ks); + kp_init_ansilib(ks); + + if (alloc_kp_percpu_data()) + goto out; + + if (kp_probe_init(ks)) + goto out; + + return ks; + + out: + G(ks)->exit = 1; + kp_final_exit(ks); + return NULL; +} + diff --git a/drivers/staging/ktap/scripts/basic/backtrace.kp b/drivers/staging/ktap/scripts/basic/backtrace.kp new file mode 100644 index 000000000000..39b8c3989e7f --- /dev/null +++ b/drivers/staging/ktap/scripts/basic/backtrace.kp @@ -0,0 +1,6 @@ +#!/usr/bin/env ktap + +trace sched:sched_switch { + print_backtrace() +} + diff --git a/drivers/staging/ktap/scripts/basic/event_trigger.kp b/drivers/staging/ktap/scripts/basic/event_trigger.kp new file mode 100644 index 000000000000..3cc8b04f361e --- /dev/null +++ b/drivers/staging/ktap/scripts/basic/event_trigger.kp @@ -0,0 +1,24 @@ +#!/usr/bin/env ktap + +soft_disabled = 1 +this_cpu = 0 + +trace syscalls:sys_enter_open { + print(argevent) + soft_disabled = 0 + this_cpu = cpu() +} + +trace *:* { + if (soft_disabled == 0 && cpu() == this_cpu) { + print(argevent) + } +} + +trace syscalls:sys_exit_open { + print(argevent) + if (cpu() == this_cpu) { + exit() + } +} + diff --git a/drivers/staging/ktap/scripts/basic/event_trigger_ftrace.kp b/drivers/staging/ktap/scripts/basic/event_trigger_ftrace.kp new file mode 100644 index 000000000000..7e0d7d315619 --- /dev/null +++ b/drivers/staging/ktap/scripts/basic/event_trigger_ftrace.kp @@ -0,0 +1,28 @@ +#!/usr/bin/env ktap + + +#This ktap script will output all function calling between +#sys_enter_open and sys_exit_open, in one cpu. + +soft_disabled = 1 +this_cpu = 0 + +trace syscalls:sys_enter_open { + print(argevent) + soft_disabled = 0 + this_cpu = cpu() +} + +trace ftrace:function { + if (soft_disabled == 0 && cpu() == this_cpu) { + print(argevent) + } +} + +trace syscalls:sys_exit_open { + print(argevent) + if (cpu() == this_cpu) { + exit() + } +} + diff --git a/drivers/staging/ktap/scripts/basic/ftrace.kp b/drivers/staging/ktap/scripts/basic/ftrace.kp new file mode 100644 index 000000000000..9feca2ba2318 --- /dev/null +++ b/drivers/staging/ktap/scripts/basic/ftrace.kp @@ -0,0 +1,6 @@ +#!/usr/bin/env ktap + +trace ftrace:function /ip==mutex*/ { + print(cpu(), pid(), execname(), argevent) +} + diff --git a/drivers/staging/ktap/scripts/basic/function_time.kp b/drivers/staging/ktap/scripts/basic/function_time.kp new file mode 100644 index 000000000000..e7859a396d95 --- /dev/null +++ b/drivers/staging/ktap/scripts/basic/function_time.kp @@ -0,0 +1,57 @@ +#!/usr/bin/env ktap + +#Demo for thread-local variable +# +#Note this kind of function time tracing already handled concurrent issue, +#but not aware on the recursion problem, user need to aware this limitation, +#so don't use this script to trace function which could be called recursive. + +self = {} +count_max = 0 +count_min = 0 +count_num = 0 +total_time = 0 + +printf("measure time(us) of function vfs_read\n"); + +trace probe:vfs_read { + if (execname() == "ktap") { + return + } + + self[tid()] = gettimeofday_us() +} + +trace probe:vfs_read%return { + if (execname() == "ktap") { + return + } + + if (self[tid()] == nil) { + return + } + + local durtion = gettimeofday_us() - self[tid()] + if (durtion > count_max) { + count_max = durtion + } + local min = count_min + if (min == 0 || durtion < min) { + count_min = durtion + } + + count_num = count_num + 1 + total_time = total_time + durtion + + self[tid()] = nil +} + +trace_end { + printf("avg\tmax\tmin\n"); + printf("-------------------\n") + + printf("%d\t%d\t%d\n", total_time/count_num, + count_max, count_min) +} + + diff --git a/drivers/staging/ktap/scripts/basic/kretprobe.kp b/drivers/staging/ktap/scripts/basic/kretprobe.kp new file mode 100644 index 000000000000..82de3cffa276 --- /dev/null +++ b/drivers/staging/ktap/scripts/basic/kretprobe.kp @@ -0,0 +1,6 @@ +#!/usr/bin/env ktap + +trace probe:vfs_read%return fd=$retval { + print(execname(), argevent); +} + diff --git a/drivers/staging/ktap/scripts/game/tetris.kp b/drivers/staging/ktap/scripts/game/tetris.kp new file mode 100644 index 000000000000..7125cd4e46ce --- /dev/null +++ b/drivers/staging/ktap/scripts/game/tetris.kp @@ -0,0 +1,328 @@ +#!/usr/bin/env ktap + +# +# Tetris KTAP Script +# +# Copyright (C) 2013/OCT/05 Tadaki SAKAI +# +# based on stapgames (Systemtap Game Collection) +# https://github.com/mhiramat/stapgames/blob/master/games/tetris.stp +# +# - Requirements +# Kernel Configuration: CONFIG_KPROBE_EVENT=y +# CONFIG_EVENT_TRACING=y +# CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_FS=y +# CPU Architecture : x86_64 +# +# - Setup +# $ sudo mount -t debugfs none /sys/kernel/debug/ +# +# $ git clone https://github.com/ktap/ktap +# $ cd ktap +# $ make 2>&1 | tee ../make.log +# $ sudo make load +# $ sudo sh -c 'echo 50000 > /sys/module/ktapvm/parameters/max_exec_count' +# +# - Run Tetris +# $ sudo ./ktap scripts/game/tetris.kp +# + + +# +# utils +# + +function rand(max) { + r = gettimeofday_us() + if (r < 0) { + r = r * -1 + } + return r % max +} + +color_table = {} +color_table["Black"] = 40 +color_table["Red"] = 41 +color_table["Green"] = 42 +color_table["Yellow"] = 43 +color_table["Blue"] = 44 +color_table["Purple"] = 45 +color_table["Cyan"] = 46 +color_table["White"] = 47 + +function get_color_number(txt) { + return color_table[txt] +} + +color_table_text = {} +color_table_text[40] = "Black" +color_table_text[41] = "Red" +color_table_text[42] = "Green" +color_table_text[43] = "Yellow" +color_table_text[44] = "Blue" +color_table_text[45] = "Purple" +color_table_text[46] = "Cyan" +color_table_text[47] = "White" + +function get_color_text(num) { + return color_table_text[num] +} + +function update_display() { + for (i = 0, 239, 1) { + if ((i % 12 - 11) != 0) { + tmp = "" + } else { + tmp = "\n" + } + + if (display_buffer[240 + i] == back_text) { + printf("%s%s", back_text, tmp) + } else { + ctext = display_buffer[240 + i] + ansi.set_color2(get_color_number(ctext), + get_color_number(ctext)) + printf(" %s", tmp) + ansi.reset_color() + } + + # clear the display buffer + display_buffer[240 + i] = display_buffer[i] + } + + printf("%d\n",point) +} + + +# +# global value +# + +key_code = 0 +point = 0 +block_number = 0 +height = 0 +height_update = 0 + +destination_position = {} +back_text = {} +block_color = {} +display_buffer = {} + +block_data0 = {} +block_data1 = {} +block_data2 = {} +block_data3 = {} +block_data4 = {} +block_data5 = {} +block_data6 = {} +block_table = {} + +# +# Initialize +# + +# Create blocks +# block is represented by the position from the center. +# Every block has "L" part in the center except for a bar. +block_data0[0] = -11 # non-"L" part for each block +block_data1[0] = -24 +block_data2[0] = 2 +block_data3[0] = 13 +block_data4[0] = -13 +block_data5[0] = -1 +block_data6[0] = 2 + +block_table[0] = block_data0 +block_table[1] = block_data1 +block_table[2] = block_data2 +block_table[3] = block_data3 +block_table[4] = block_data4 +block_table[5] = block_data5 +block_table[6] = block_data6 + +for (i = 0, len(block_table) - 1, 1) { + # common "L" part + block_table[i][1] = 0 + block_table[i][2] = 1 + block_table[i][3] = -12 +} + +block_table[6][3] = -1 # bar is not common +# Position: 1 row has 12 columns, +# and (x, y) is represented by h = x + y * 12.p +height = 17 # First block position (center) + +for (i = 0, 240, 1) { + # Wall and Floor (sentinel) + if (((i % 12) < 2) || (i > 228)) { + block_color = "White" + tmp = block_color + } else { + back_text = " " + tmp = back_text + } + display_buffer[i - 1] = tmp + display_buffer[240 + i - 1] = tmp +} + +block_number = rand(len(color_table) - 1) +block_color = get_color_text(block_number + 40) + +ansi.clear_screen() + + +# +# Key Input +# + +trace probe:kbd_event handle=%di event_type=%si event_code=%dx value=%cx { + # Only can run it in x86_64 + # + # Register follow x86_64 call conversion: + # + # x86_64: + # %rcx 4 argument + # %rdx 3 argument + # %rsi 2 argument + # %rdi 1 argument + + local event_code = arg4 + local value = arg5 + + if (value != 0) { + if ((event_code - 4) != 0) { + key_code = event_code + } + } +} + + +# +# timer +# + +tick-200ms { + ansi.clear_screen() + + f = 0 # move/rotate flag + + if (key_code != 0) { # if key is pressed + if(key_code != 103) { #move left or right + # d: movement direction + if ((key_code - 105) != 0) { + if ((key_code - 106) != 0) { + d = 0 + } else { + d = 1 + } + } else { + d = -1 + } + + for (i = 0, 3, 1) { # check if the block can be moved + # destination is free + if (display_buffer[height + + block_table[block_number][i] + d] + != back_text) { + f = 1 + } + } + # move if destinations of every block are free + if (f == 0) { + height = height + d + } + } else { # rotate + for (i = 0, 3, 1) { # check if block can be rotated + # each block position + p = block_table[block_number][i] + + # destination x pos(p/12 rounded) + v = (p * 2 + 252) / 24 - 10 + w = p - v * 12 # destination y pos + + # destination position + destination_position[i] = w * 12 - v + + # check if desetination is free + if (display_buffer[height + + destination_position[i]] != back_text) { + f = 1 + } + } + + if (f == 0) { + # rotate if destinations of every block + # are free + for (i = 0, 3, 1) { + block_table[block_number][i] = + destination_position[i] + } + } + } + } + key_code = 0 # clear the input key + + f = 0 + for (i = 0, 3, 1) { # drop 1 row + # check if destination is free + p = height + block_table[block_number][i] + if (display_buffer[12 + p] != back_text) { + f = 1 + } + + # copy the moving block to display buffer + display_buffer[240 + p] = block_color + } + + if ((f == 1) && (height == 17)) { + update_display() + exit() # exit if there are block at initial position + } + + height_update = !height_update + if (height_update != 0) { + if(f != 0) { # the block can't drop anymore + for (i = 0, 3, 1) { + # fix the block + display_buffer[height + + block_table[block_number][i]] = block_color + } + # determin the next block + block_number = rand(len(color_table) - 1) + + block_color = get_color_text(block_number + 40) + + height = 17 # make the block to initial position + } else { + height = height + 12 # drop the block 1 row + } + } + + k = 1 + for (i = 18, 0, -1) { #check if line is filled + # search for filled line + j = 10 + while ((j > 0) && + (display_buffer[i * 12 + j] != back_text)) { + j = j - 1 + } + + if (j == 0) { # filled! + # add a point: 1 line - 1 point, ..., tetris - 10points + point = point + k + k = k + 1 + + # drop every upper block + j = (i + 1) * 12 + i = i + 1 + while (j > 2 * 12) { + j = j - 1 + display_buffer[j] = display_buffer[j - 12] + } + } + } + + update_display() +} diff --git a/drivers/staging/ktap/scripts/helloworld.kp b/drivers/staging/ktap/scripts/helloworld.kp new file mode 100644 index 000000000000..5673c15b0226 --- /dev/null +++ b/drivers/staging/ktap/scripts/helloworld.kp @@ -0,0 +1,3 @@ +#!/usr/bin/env ktap + +print("Hello World! I am ktap") diff --git a/drivers/staging/ktap/scripts/interrupt/hardirq_time.kp b/drivers/staging/ktap/scripts/interrupt/hardirq_time.kp new file mode 100644 index 000000000000..1d3c33e859d1 --- /dev/null +++ b/drivers/staging/ktap/scripts/interrupt/hardirq_time.kp @@ -0,0 +1,25 @@ +#!/usr/bin/env ktap + +#this script output each average consumimg time of each hardirq +s = aggr_table() +map = {} + +trace irq:irq_handler_entry { + map[cpu()] = gettimeofday_us() +} + +trace irq:irq_handler_exit { + local entry_time = map[cpu()] + if (entry_time == nil) { + return; + } + + s[arg1] = avg(gettimeofday_us() - entry_time) + map[cpu()] = nil +} + +trace_end { + print("hardirq average executing time (us)") + histogram(s) +} + diff --git a/drivers/staging/ktap/scripts/interrupt/softirq_time.kp b/drivers/staging/ktap/scripts/interrupt/softirq_time.kp new file mode 100644 index 000000000000..7e1a9d8a9172 --- /dev/null +++ b/drivers/staging/ktap/scripts/interrupt/softirq_time.kp @@ -0,0 +1,25 @@ +#!/usr/bin/env ktap + +#this script output each average consumimg time of each softirq line +s = aggr_table() +map = {} + +trace irq:softirq_entry { + map[cpu()] = gettimeofday_us() +} + +trace irq:softirq_exit { + local entry_time = map[cpu()] + if (entry_time == nil) { + return; + } + + s[arg1] = avg(gettimeofday_us() - entry_time) + map[cpu()] = nil +} + +trace_end { + print("softirq average executing time (us)") + histogram(s) +} + diff --git a/drivers/staging/ktap/scripts/io/kprobes-do-sys-open.kp b/drivers/staging/ktap/scripts/io/kprobes-do-sys-open.kp new file mode 100644 index 000000000000..a15f911a1804 --- /dev/null +++ b/drivers/staging/ktap/scripts/io/kprobes-do-sys-open.kp @@ -0,0 +1,20 @@ +#!/usr/bin/env ktap + +#Only can run it in x86_64 +# +#Register follow x86_64 call conversion: +# +#x86_64: +# %rcx 4 argument +# %rdx 3 argument +# %rsi 2 argument +# %rdi 1 argument + +trace probe:do_sys_open dfd=%di filename=%si flags=%dx mode=%cx { + printf("[do_sys_open entry]: (%s) open file (%s)\n", + execname(), user_string(arg3)) +} + +trace probe:do_sys_open%return fd=$retval { + printf("[do_sys_open exit]: return fd (%d)\n", arg3) +} diff --git a/drivers/staging/ktap/scripts/io/traceio.kp b/drivers/staging/ktap/scripts/io/traceio.kp new file mode 100644 index 000000000000..8a95a2534384 --- /dev/null +++ b/drivers/staging/ktap/scripts/io/traceio.kp @@ -0,0 +1,56 @@ +#! /usr/bin/env ktap + +# Based on systemtap traceio.stp + +#this script is broken, fix it soon. + +reads = aggr_table() +writes = aggr_table() +total_io = aggr_table() + +trace syscalls:sys_exit_read { + reads[execname()] = sum(arg2) + total_io[execname()] = sum(arg2) +} + +trace syscalls:sys_exit_write { + writes[execname()] = sum(arg2) + total_io[execname()] = sum(arg2) +} + +function humanread_digit(bytes) { + if (bytes > 1024*1024*1024) { + return bytes/1024/1024/1024 + } elseif (bytes > 1024*1024) { + return bytes/1024/1024 + } elseif (bytes > 1024) { + return bytes/1024 + } else { + return bytes + } +} + +function humanread_x(bytes) { + if (bytes > 1024*1024*1024) { + return " GiB" + } elseif (bytes > 1024*1024) { + return " MiB" + } elseif (bytes > 1024) { + return " KiB" + } else { + return " B" + } +} + +tick-1s { + ansi.clear_screen() + for (exec, count in pairs(total_io)) { + local readnum = reads[exec] + local writenum = writes[exec] + printf("%15s r: %12d%s w: %12d%s\n", exec, + humanread_digit(readnum), humanread_x(readnum), + humanread_digit(writenum), humanread_x(writenum)) + } + printf("\n") +} + diff --git a/drivers/staging/ktap/scripts/mem/kmalloc-top.kp b/drivers/staging/ktap/scripts/mem/kmalloc-top.kp new file mode 100644 index 000000000000..f18ed9fc64cf --- /dev/null +++ b/drivers/staging/ktap/scripts/mem/kmalloc-top.kp @@ -0,0 +1,17 @@ +#!/usr/bin/env ktap + +kmalloc_stack = {} + +trace kmem:kmalloc { + kmalloc_stack[backtrace()] += 1 +} + +tick-60s { + for (k, v in pairs(kmalloc_stack)) { + print(k) + printf("%d\n\n", v) + } + + exit() +} + diff --git a/drivers/staging/ktap/scripts/mem/kmem.kp b/drivers/staging/ktap/scripts/mem/kmem.kp new file mode 100644 index 000000000000..c6f2c99c54cd --- /dev/null +++ b/drivers/staging/ktap/scripts/mem/kmem.kp @@ -0,0 +1,30 @@ +#!/usr/bin/env ktap + +count1 = 0 +trace kmem:kmalloc { + count1 = count1 + 1 +} + +count2 = 0 +trace kmem:kfree { + count2 = count2 + 1 +} + +count3 = 0 +trace kmem:mm_page_alloc { + count3 = count3 + 1 +} + +count4 = 0 +trace kmem:mm_page_free { + count4 = count4 + 1 +} + +trace_end { + print("\n") + print("kmem:kmalloc:\t", count1) + print("kmem:kfree:\t", count2) + print("kmem:mm_page_alloc:", count3) + print("kmem:mm_page_free:", count4) + print("trace ending\n") +} diff --git a/drivers/staging/ktap/scripts/profiling/function_profiler.kp b/drivers/staging/ktap/scripts/profiling/function_profiler.kp new file mode 100644 index 000000000000..589017fe83b4 --- /dev/null +++ b/drivers/staging/ktap/scripts/profiling/function_profiler.kp @@ -0,0 +1,41 @@ +#!/usr/bin/env ktap + +#kernel function profile +#You can use this script to know what function is called frequently, +#without enable CONFIG_FUNCTION_PROFILER in kernel. + +s = aggr_table() + +trace ftrace:function { + s[arg1] = count() +} + +trace_end { + histogram(s) +} + +#sample output +#^C +# value ------------- Distribution ------------- count +# sub_preempt_count | @@@@@ 34904 +# add_preempt_count | @@@@@ 33435 +# nsecs_to_jiffies64 | @@@ 19919 +# irqtime_account_process_tick... | @ 9970 +# account_idle_time | @ 9880 +# _raw_spin_lock | 5100 +# _raw_spin_unlock | 5021 +# _raw_spin_unlock_irqrestore | 4235 +# _raw_spin_lock_irqsave | 4232 +# __rcu_read_lock | 3373 +# __rcu_read_unlock | 3373 +# lookup_address | 2392 +# pfn_range_is_mapped | 2384 +# update_cfs_rq_blocked_load | 1983 +# idle_cpu | 1808 +# ktime_get | 1394 +# _raw_spin_unlock_irq | 1270 +# _raw_spin_lock_irq | 1091 +# update_curr | 950 +# irqtime_account_irq | 950 +# ... | +# diff --git a/drivers/staging/ktap/scripts/profiling/stack_profile.kp b/drivers/staging/ktap/scripts/profiling/stack_profile.kp new file mode 100644 index 000000000000..97945602fcea --- /dev/null +++ b/drivers/staging/ktap/scripts/profiling/stack_profile.kp @@ -0,0 +1,26 @@ +#!/usr/bin/env ktap + +# This ktap script samples stacktrace of system per 10us, +# you can use generated output to make a flame graph. +# +# Flame Graphs: +# http://dtrace.org/blogs/brendan/2012/03/17/linux-kernel-performance-flame-graphs/ + +s = aggr_table() + +profile-10us { + s[backtrace()] = count() +} + +tick-60s { + exit() +} + +trace_end { + for (k, v in pairs(s)) { + print(k) + print(v) + print() + } +} + diff --git a/drivers/staging/ktap/scripts/schedule/sched_transition.kp b/drivers/staging/ktap/scripts/schedule/sched_transition.kp new file mode 100644 index 000000000000..eb54b09c3248 --- /dev/null +++ b/drivers/staging/ktap/scripts/schedule/sched_transition.kp @@ -0,0 +1,5 @@ +#!/usr/bin/env ktap + +trace sched:sched_switch { + printf("%s ... ", arg1) +} diff --git a/drivers/staging/ktap/scripts/schedule/schedtimes.kp b/drivers/staging/ktap/scripts/schedule/schedtimes.kp new file mode 100644 index 000000000000..acef904a2cae --- /dev/null +++ b/drivers/staging/ktap/scripts/schedule/schedtimes.kp @@ -0,0 +1,125 @@ +#!/usr/vin/env ktap + +#schedtimer.kp +#Initially inspired by Systemtap schedtimes.stp +#and more bugfree compare with Systemtap's version +# +#Note that the time value is associate with pid, not with execname strictly, +#sometime you will found there have sleep time for command "ls", the reason +#is that sleep time is belong to parent process bash, so clear on this. + +RUNNING = 0 +QUEUED = 1 +SLEEPING = 2 +DEAD = 64 + +run_time = {} +queued_time = {} +sleep_time = {} +io_wait_time = {} + +pid_state = {} +pid_names = {} +prev_timestamp = {} +io_wait = {} + +trace sched:sched_switch { + local prev_comm = arg1 + local prev_pid = arg2 + local prev_state = arg4 + local next_comm = arg5 + local next_pid = arg6 + local t = gettimeofday_us() + + if (pid_state[prev_pid] == nil) { + #do nothing + } elseif (pid_state[prev_pid] == RUNNING) { + run_time[prev_pid] += t - prev_timestamp[prev_pid] + } elseif (pid_state[prev_pid] == QUEUED) { + #found this: + #sched_wakeup comm=foo + #sched_switch prev_comm=foo + run_time[prev_pid] += t - prev_timestamp[prev_pid] + } + + pid_names[prev_pid] = prev_comm + prev_timestamp[prev_pid] = t + + if (prev_state == DEAD) { + pid_state[prev_pid] = DEAD + } elseif (prev_state > 0) { + if (in_iowait() == 1) { + io_wait[prev_pid] = 1 + } + pid_state[prev_pid] = SLEEPING + } elseif (prev_state == 0) { + pid_state[prev_pid] = QUEUED + } + + if (pid_state[next_pid] == nil) { + pid_state[next_pid] = RUNNING + } elseif (pid_state[next_pid] == QUEUED) { + queued_time[next_pid] += t - prev_timestamp[next_pid] + pid_state[next_pid] = RUNNING + } + + pid_names[next_pid] = next_comm + prev_timestamp[next_pid] = t +} + +trace sched:sched_wakeup, sched:sched_wakeup_new { + local comm = arg1 + local wakeup_pid = arg2 + local success = arg4 + local t = gettimeofday_us() + + if (pid_state[wakeup_pid] == nil) { + #do nothing + } elseif (pid_state[wakeup_pid] == SLEEPING) { + local durtion = t - prev_timestamp[wakeup_pid] + + sleep_time[wakeup_pid] += durtion + if (io_wait[wakeup_pid] == 1) { + io_wait_time[wakeup_pid] += durtion + io_wait[wakeup_pid] = 0 + } + } elseif (pid_state[wakeup_pid] == RUNNING) { + return + } + + pid_names[wakeup_pid] = comm + prev_timestamp[wakeup_pid] = t + pid_state[wakeup_pid] = QUEUED +} + +trace_end { + local t = gettimeofday_us() + + for (pid, state in pairs(pid_state)) { + local durtion = t - prev_timestamp[pid] + if (state == SLEEPING) { + sleep_time[pid] += durtion + } elseif (state == QUEUED) { + queued_time[pid] += durtion + } elseif (state == RUNNING) { + run_time[pid] += durtion + } + } + + printf ("%16s: %6s %10s %10s %10s %10s %10s\n\n", + "execname", "pid", "run(us)", "sleep(us)", "io_wait(us)", + "queued(us)", "total(us)") + + for (pid, time in pairs(run_time)) { + if (sleep_time[pid] == nil) { + sleep_time[pid] = 0 + } + if (queued_time[pid] == nil) { + queue_time[pid] = 0 + } + printf("%16s: %6d %10d %10d %10d %10d %10d\n", + pid_names[pid], pid, run_time[pid], sleep_time[pid], + io_wait_time[pid], queued_time[pid], + run_time[pid] + sleep_time[pid] + queued_time[pid]); + } +} diff --git a/drivers/staging/ktap/scripts/syscalls/errinfo.kp b/drivers/staging/ktap/scripts/syscalls/errinfo.kp new file mode 100644 index 000000000000..049031b3e374 --- /dev/null +++ b/drivers/staging/ktap/scripts/syscalls/errinfo.kp @@ -0,0 +1,145 @@ +#!/usr/bin/env ktap + +#errdesc get from include/uapi/asm-generic/errno*.h +errdesc = { + [1] = "Operation not permitted", #EPERM + [2] = "No such file or directory", #ENOENT + [3] = "No such process", #ESRCH + [4] = "Interrupted system call", #EINRT + [5] = "I/O error", #EIO + [6] = "No such device or address", #ENXIO + [7] = "Argument list too long", #E2BIG + [8] = "Exec format error", #ENOEXEC + [9] = "Bad file number", #EBADF + [10] = "No child processes", #ECHILD + [11] = "Try again", #EAGAIN + [12] = "Out of memory", #ENOMEM + [13] = "Permission denied", #EACCES + [14] = "Bad address", #EFAULT + [15] = "Block device required", #ENOTBLK + [16] = "Device or resource busy", #EBUSY + [17] = "File exists", #EEXIST + [18] = "Cross-device link", #EXDEV + [19] = "No such device", #ENODEV + [20] = "Not a directory", #ENOTDIR + [21] = "Is a directory", #EISDIR + [22] = "Invalid argument", #EINVAL + [23] = "File table overflow", #ENFILE + [24] = "Too many open files", #EMFILE + [25] = "Not a typewriter", #ENOTTY + [26] = "Text file busy", #ETXTBSY + [27] = "File too large", #EFBIG + [28] = "No space left on device", #ENOSPC + [29] = "Illegal seek", #ESPIPE + [30] = "Read-only file system", #EROFS + [31] = "Too many links", #EMLINK + [32] = "Broken pipe", #EPIPE + [33] = "Math argument out of domain of func", #EDOM + [34] = "Math result not representable", #ERANGE + + [35] = "Resource deadlock would occur", #EDEADLK + [36] = "File name too long", #ENAMETOOLONG + [37] = "No record locks available", #ENOLCK + [38] = "Function not implemented", #ENOSYS + [39] = "Directory not empty", #ENOTEMPTY + [40] = "Too many symbolic links encountered", #ELOOP + [42] = "No message of desired type", #ENOMSG + [43] = "Identifier removed", #EIDRM + [44] = "Channel number out of range", #ECHRNG + [45] = "Level 2 not synchronized", #EL2NSYNC + [46] = "Level 3 halted", #EL3HLT + [47] = "Level 3 reset", #EL3RST + [48] = "Link number out of range", #ELNRNG + [49] = "Protocol driver not attached", #EUNATCH + [50] = "No CSI structure available", #ENOCSI + [51] = "Level 2 halted", #EL2HLT + [52] = "Invalid exchange", #EBADE + [53] = "Invalid request descriptor", #EBADR + [54] = "Exchange full", #EXFULL + [55] = "No anode", #ENOANO + [56] = "Invalid request code", #EBADRQC + [57] = "Invalid slot", #EBADSLT + + [59] = "Bad font file format", #EBFONT + [60] = "Device not a stream", #ENOSTR + [61] = "No data available", #ENODATA + [62] = "Timer expired", #ETIME + [63] = "Out of streams resources", #ENOSR + [64] = "Machine is not on the network", #ENONET + [65] = "Package not installed", #ENOPKG + [66] = "Object is remote", #EREMOTE + [67] = "Link has been severed", #ENOLINK + [68] = "Advertise error", #EADV + [69] = "Srmount error", #ESRMNT + [70] = "Communication error on send", #ECOMM + [71] = "Protocol error", #EPROTO + [72] = "Multihop attempted", #EMULTIHOP + [73] = "RFS specific error", #EDOTDOT + [74] = "Not a data message", #EBADMSG + [75] = "Value too large for defined data type", #EOVERFLOW + [76] = "Name not unique on network", #ENOTUNIQ + [77] = "File descriptor in bad state", #EBADFD + [78] = "Remote address changed", #EREMCHG + [79] = "Can not access a needed shared library", #ELIBACC + [80] = "Accessing a corrupted shared library", #ELIBBAD + [81] = ".lib section in a.out corrupted", #ELIBSCN + [82] = "Attempting to link in too many shared libraries", #ELIBMAX + [83] = "Cannot exec a shared library directly", #ELIBEXEC + [84] = "Illegal byte sequence", #EILSEQ + [85] = "Interrupted system call should be restarted", #ERESTART + [86] = "Streams pipe error", #ESTRPIPE + [87] = "Too many users", #EUSERS + [88] = "Socket operation on non-socket", #ENOTSOCK + [89] = "Destination address required", #EDESTADDRREQ + [90] = "Message too long", #EMSGSIZE + [91] = "Protocol wrong type for socket", #EPROTOTYPE + [92] = "Protocol not available", #ENOPROTOOPT + [93] = "Protocol not supported", #EPROTONOSUPPORT + [94] = "Socket type not supported", #ESOCKTNOSUPPORT + [95] = "Operation not supported on transport endpoint", #EOPNOTSUPP + [96] = "Protocol family not supported", #EPFNOSUPPORT + [97] = "Address family not supported by protocol", #EAFNOSUPPORT + [98] = "Address already in use", #EADDRINUSE + [99] = "Cannot assign requested address", #EADDRNOTAVAIL + [100] = "Network is down", #ENETDOWN + [101] = "Network is unreachable", #ENETUNREACH + [102] = "Network dropped connection because of reset", #ENETRESET + [103] = "Software caused connection abort", #ECONNABORTED + [104] = "Connection reset by peer", #ECONNRESET + [105] = "No buffer space available", #ENOBUFS + [106] = "Transport endpoint is already connected", #EISCONN + [107] = "Transport endpoint is not connected", #ENOTCONN + [108] = " Cannot send after transport endpoint shutdown", #ESHUTDOWN + [109] = "Too many references: cannot splice", #ETOOMANYREFS + [110] = "Connection timed out", #ETIMEDOUT + [111] = "Connection refused", #ECONNREFUSED + [112] = "Host is down", #EHOSTDOWN + [113] = "No route to host", #EHOSTUNREACH + [114] = "Operation already in progress", #EALREADY + [115] = "Operation now in progress", #EINPROGRESS + [116] = "Stale NFS file handle", #ESTALE + [117] = "Structure needs cleaning", #EUCLEAN + [118] = "Not a XENIX named type file", #ENOTNAM + [119] = "No XENIX semaphores available", #ENAVAIL + [120] = "Is a named type file", #EISNAM + [121] = "Remote I/O error", #EREMOTEIO + [122] = "Quota exceeded", #EDQUOT + [123] = "No medium found", #ENOMEDIUM + [124] = "Wrong medium type", #EMEDIUMTYPE + [125] = "Operation Canceled", #ECANCELED + [126] = "Required key not available", #ENOKEY + [127] = "Key has expired", #EKEYEXPIRED + [128] = "Key has been revoked", #EKEYREVOKED + [129] = "Key was rejected by service", #EKEYREJECTED + [130] = "Owner died", #EOWNERDEAD + [131] = "State not recoverable", #ENOTRECOVERABLE + +} + +trace syscalls:sys_exit_* { + if (arg2 < 0) { + local errno = -arg2 + printf("%-15s%-20s\t%d\t%-30s\n", + execname(), argname, errno, errdesc[errno]) + } +} diff --git a/drivers/staging/ktap/scripts/syscalls/sctop.kp b/drivers/staging/ktap/scripts/syscalls/sctop.kp new file mode 100644 index 000000000000..6df45cb98178 --- /dev/null +++ b/drivers/staging/ktap/scripts/syscalls/sctop.kp @@ -0,0 +1,14 @@ +#! /usr/bin/env ktap + +#this script is broken, fix it soon. +s = {} + +trace syscalls:sys_enter_* { + s[argname] += 1 +} + +tick-5s { + ansi.clear_screen() + histogram(s) + delete(s) +} diff --git a/drivers/staging/ktap/scripts/syscalls/syscalls.kp b/drivers/staging/ktap/scripts/syscalls/syscalls.kp new file mode 100644 index 000000000000..8bbaacad68ac --- /dev/null +++ b/drivers/staging/ktap/scripts/syscalls/syscalls.kp @@ -0,0 +1,6 @@ +#!/usr/bin/env ktap + +trace syscalls:* { + print(cpu(), pid(), execname(), argevent) +} + diff --git a/drivers/staging/ktap/scripts/syscalls/syscalls_count.kp b/drivers/staging/ktap/scripts/syscalls/syscalls_count.kp new file mode 100644 index 000000000000..363c6226e8a9 --- /dev/null +++ b/drivers/staging/ktap/scripts/syscalls/syscalls_count.kp @@ -0,0 +1,56 @@ +#!/usr/bin/env ktap + +s = aggr_table() + +trace syscalls:sys_enter_* { + s[argname] = count() +} + +trace_end { + histogram(s) +} + +print("Press Control-C to stop.") + +#Result: +# +#[root@jovi ktap]# ./ktap scripts/syscalls_histogram.kp +#^C +# value ------------- Distribution ------------- count +# sys_enter_rt_sigprocmask |@@@@@@ 326 +# sys_enter_read |@@@@@ 287 +# sys_enter_close |@@@@ 236 +# sys_enter_open |@@@@ 222 +# sys_enter_stat64 |@@ 132 +# sys_enter_select |@@ 123 +# sys_enter_rt_sigaction |@@ 107 +# sys_enter_poll |@ 72 +# sys_enter_write |@ 70 +# sys_enter_mmap_pgoff |@ 58 +# sys_enter_fstat64 | 41 +# sys_enter_nanosleep | 23 +# sys_enter_access | 20 +# sys_enter_mprotect | 18 +# sys_enter_geteuid | 17 +# sys_enter_getegid | 16 +# sys_enter_getuid | 16 +# sys_enter_getgid | 16 +# sys_enter_brk | 15 +# sys_enter_waitpid | 11 +# sys_enter_time | 10 +# sys_enter_ioctl | 9 +# sys_enter_munmap | 9 +# sys_enter_fcntl64 | 7 +# sys_enter_dup2 | 7 +# sys_enter_clone | 6 +# sys_enter_exit_group | 6 +# sys_enter_execve | 4 +# sys_enter_pipe | 3 +# sys_enter_gettimeofday | 3 +# sys_enter_getdents | 2 +# sys_enter_getgroups | 2 +# sys_enter_statfs64 | 2 +# sys_enter_lseek | 2 +# sys_enter_openat | 1 +# sys_enter_newuname | 1 + diff --git a/drivers/staging/ktap/scripts/syscalls/syscalls_count_by_proc.kp b/drivers/staging/ktap/scripts/syscalls/syscalls_count_by_proc.kp new file mode 100644 index 000000000000..7b7d722b893d --- /dev/null +++ b/drivers/staging/ktap/scripts/syscalls/syscalls_count_by_proc.kp @@ -0,0 +1,24 @@ +#!/usr/bin/env ktap + +s = aggr_table() + +trace syscalls:sys_enter_* { + s[execname()] = count() +} + +trace_end { + histogram(s) +} + +print("Press Control-C to stop.") + +#Result: +# +#[root@jovi ktap]# ./ktap scripts/syscalls_histogram2.kp +#^C +# value ------------- Distribution ------------- count +# sshd |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 196 +# iscsid |@@@@ 24 +# sendmail |@ 9 + + diff --git a/drivers/staging/ktap/scripts/tracepoints/eventcount.kp b/drivers/staging/ktap/scripts/tracepoints/eventcount.kp new file mode 100644 index 000000000000..9bc357fca56b --- /dev/null +++ b/drivers/staging/ktap/scripts/tracepoints/eventcount.kp @@ -0,0 +1,212 @@ +#!/usr/bin/env ktap + +# showing all tracepoints in histogram style + +s = {} + +trace *:* { + s[argname] += 1 +} + +trace_end { + histogram(s) +} + +print("Press Control-C to stop.") + +#Results: +#^C +# +# value ------------- Distribution ------------- count +# rcu_utilization |@@@@@ 225289 +# cpu_idle |@@@ 120168 +# sched_wakeup |@@ 91950 +# timer_cancel |@@ 91232 +# timer_start |@@ 91201 +# sched_stat_sleep |@@ 90981 +# timer_expire_exit |@@ 90634 +# timer_expire_entry |@@ 90625 +# hrtimer_cancel |@ 75411 +# hrtimer_start |@ 74946 +# softirq_raise |@ 63117 +# softirq_exit |@ 63109 +# softirq_entry |@ 63094 +# sched_switch |@ 62331 +# sched_stat_wait |@ 60491 +# hrtimer_expire_exit |@ 47538 +# hrtimer_expire_entry |@ 47530 +# sched_stat_runtime | 2780 +# kmem_cache_free | 2684 +# kmem_cache_alloc | 2415 +# kfree | 2288 +# sys_exit | 2145 +# sys_enter | 2145 +# sys_exit_rt_sigprocmask | 1000 +# sys_enter_rt_sigprocmask | 1000 +# timer_init | 912 +# sched_stat_blocked | 685 +# kmalloc | 667 +# workqueue_execute_end | 621 +# workqueue_execute_start | 621 +# sys_enter_select | 566 +# sys_exit_select | 566 +# sys_enter_read | 526 +# sys_exit_read | 526 +# mm_page_free | 478 +# mm_page_alloc | 427 +# mm_page_free_batched | 382 +# net_dev_queue | 296 +# net_dev_xmit | 296 +# consume_skb | 296 +# sys_exit_write | 290 +# sys_enter_write | 290 +# kfree_skb | 289 +# kmem_cache_alloc_node | 269 +# kmalloc_node | 263 +# sys_enter_close | 249 +# sys_exit_close | 249 +# hrtimer_init | 248 +# netif_receive_skb | 242 +# sys_enter_open | 237 +# sys_exit_open | 237 +# napi_poll | 226 +# sched_migrate_task | 207 +# sys_exit_poll | 173 +# sys_enter_poll | 173 +# workqueue_queue_work | 152 +# workqueue_activate_work | 152 +# sys_enter_stat64 | 133 +# sys_exit_stat64 | 133 +# sys_exit_rt_sigaction | 133 +# sys_enter_rt_sigaction | 133 +# irq_handler_entry | 125 +# irq_handler_exit | 125 +# mm_page_alloc_zone_locked | 99 +# sys_exit_mmap_pgoff | 66 +# sys_enter_mmap_pgoff | 66 +# sys_exit_fstat64 | 54 +# sys_enter_fstat64 | 54 +# sys_enter_nanosleep | 51 +# sys_exit_nanosleep | 51 +# block_bio_queue | 46 +# block_bio_remap | 46 +# block_bio_complete | 46 +# mix_pool_bytes | 44 +# mm_page_pcpu_drain | 31 +# sys_exit_time | 23 +# sys_enter_time | 23 +# sys_exit_access | 20 +# sys_enter_access | 20 +# mix_pool_bytes_nolock | 18 +# sys_enter_mprotect | 18 +# sys_exit_mprotect | 18 +# sys_enter_geteuid | 17 +# sys_exit_geteuid | 17 +# sys_enter_munmap | 17 +# sys_exit_munmap | 17 +# block_getrq | 16 +# sys_enter_getuid | 16 +# sys_enter_getgid | 16 +# sys_exit_getgid | 16 +# sys_exit_getuid | 16 +# block_rq_issue | 16 +# scsi_dispatch_cmd_start | 16 +# block_rq_complete | 16 +# scsi_dispatch_cmd_done | 16 +# sys_enter_getegid | 16 +# sys_exit_getegid | 16 +# block_rq_insert | 16 +# skb_copy_datagram_iovec | 15 +# sys_enter_brk | 15 +# sys_exit_brk | 15 +# credit_entropy_bits | 14 +# wbc_writepage | 14 +# sys_exit_clone | 12 +# block_touch_buffer | 12 +# sched_process_wait | 11 +# sys_enter_waitpid | 11 +# sys_exit_waitpid | 11 +# writeback_written | 10 +# writeback_start | 10 +# writeback_queue_io | 10 +# ext4_es_lookup_extent_enter | 9 +# sys_enter_ioctl | 9 +# sys_exit_ioctl | 9 +# ext4_ext_map_blocks_enter | 9 +# ext4_ext_map_blocks_exit | 9 +# ext4_es_lookup_extent_exit | 9 +# ext4_es_insert_extent | 9 +# ext4_ext_show_extent | 8 +# extract_entropy | 8 +#ext4_es_find_delayed_extent_exit | 8 +# ext4_es_find_delayed_extent_... | 8 +# writeback_pages_written | 7 +# sys_exit_dup2 | 7 +# sys_enter_dup2 | 7 +# signal_generate | 7 +# sys_enter_fcntl64 | 7 +# sys_exit_fcntl64 | 7 +# global_dirty_state | 7 +# writeback_dirty_inode_start | 7 +# block_bio_backmerge | 7 +# writeback_dirty_inode | 7 +# sched_wakeup_new | 6 +# sched_process_free | 6 +# sys_enter_exit_group | 6 +# task_newtask | 6 +# sys_enter_clone | 6 +# sched_process_fork | 6 +# sched_process_exit | 6 +# sys_exit_gettimeofday | 5 +# signal_deliver | 5 +# sys_enter_gettimeofday | 5 +# writeback_single_inode | 4 +# sys_enter_execve | 4 +# task_rename | 4 +# sched_process_exec | 4 +# block_dirty_buffer | 4 +# sys_exit_execve | 4 +# block_unplug | 4 +# sched_stat_iowait | 4 +# writeback_single_inode_start | 4 +# block_plug | 4 +# writeback_write_inode | 3 +# sys_enter_pipe | 3 +# writeback_dirty_page | 3 +# writeback_write_inode_start | 3 +# ext4_mark_inode_dirty | 3 +# ext4_journal_start | 3 +# sys_exit_pipe | 3 +# jbd2_drop_transaction | 2 +# jbd2_commit_locking | 2 +# jbd2_commit_flushing | 2 +# jbd2_handle_start | 2 +# jbd2_run_stats | 2 +# sys_exit_getdents | 2 +# jbd2_checkpoint_stats | 2 +# sys_enter_getgroups | 2 +# jbd2_start_commit | 2 +# jbd2_end_commit | 2 +# ext4_da_writepages | 2 +# jbd2_handle_stats | 2 +# sys_enter_statfs64 | 2 +# sys_exit_statfs64 | 2 +# sys_exit_getgroups | 2 +# sys_exit_lseek | 2 +# sys_enter_lseek | 2 +# sys_enter_getdents | 2 +# ext4_da_write_pages | 2 +# jbd2_commit_logging | 2 +# ext4_request_blocks | 1 +# sys_exit_openat | 1 +# ext4_discard_preallocations | 1 +# ext4_mballoc_alloc | 1 +# sys_enter_openat | 1 +# ext4_da_writepages_result | 1 +# ext4_allocate_blocks | 1 +# sys_enter_newuname | 1 +# ext4_da_update_reserve_space | 1 +# ext4_get_reserved_cluster_alloc | 1 +# sys_exit_newuname | 1 +# writeback_wake_thread | 1 + diff --git a/drivers/staging/ktap/scripts/tracepoints/eventcount_by_proc.kp b/drivers/staging/ktap/scripts/tracepoints/eventcount_by_proc.kp new file mode 100644 index 000000000000..8706f73d5b40 --- /dev/null +++ b/drivers/staging/ktap/scripts/tracepoints/eventcount_by_proc.kp @@ -0,0 +1,59 @@ +#!/usr/bin/env ktap + +# showing all tracepoints in histogram style + +s = aggr_table() + +trace *:* { + s[execname()] = count() +} + +trace_end { + histogram(s) +} + +print("Press Control-C to stop.") + +#Results: +#^C +# value ------------- Distribution ------------- count +# swapper/0 |@@@@@@@@@@@@ 354378 +# swapper/1 |@@@@@@@@@@ 284984 +# ps |@@@@ 115697 +# ksmtuned |@@@ 95857 +# iscsid |@@ 80008 +# awk |@ 30354 +# irqbalance | 16530 +# rcu_sched | 15892 +# sendmail | 14463 +# kworker/0:1 | 10540 +# kworker/u4:2 | 9250 +# kworker/1:2 | 7943 +# sleep | 7555 +# crond | 3911 +# ksoftirqd/0 | 3817 +# sshd | 2849 +# systemd-journal | 2209 +# migration/1 | 1601 +# migration/0 | 1350 +# dhclient | 1343 +# nm-dhcp-client. | 1208 +# ksoftirqd/1 | 1064 +# watchdog/1 | 966 +# watchdog/0 | 964 +# khugepaged | 776 +# dbus-daemon | 611 +# rpcbind | 607 +# gdbus | 529 +# NetworkManager | 399 +# jbd2/dm-1-8 | 378 +# modem-manager | 184 +# abrt-watch-log | 157 +# polkitd | 156 +# rs:main Q:Reg | 153 +# avahi-daemon | 151 +# rsyslogd | 102 +# systemd | 96 +# kworker/0:1H | 45 +# smartd | 30 + diff --git a/drivers/staging/ktap/scripts/tracepoints/tracepoints.kp b/drivers/staging/ktap/scripts/tracepoints/tracepoints.kp new file mode 100644 index 000000000000..5d088695bbf2 --- /dev/null +++ b/drivers/staging/ktap/scripts/tracepoints/tracepoints.kp @@ -0,0 +1,6 @@ +#!/usr/bin/env ktap + +trace *:* { + print(cpu(), pid(), execname(), argevent) +} + diff --git a/drivers/staging/ktap/scripts/userspace/uprobes-malloc.kp b/drivers/staging/ktap/scripts/userspace/uprobes-malloc.kp new file mode 100644 index 000000000000..14c172f8f327 --- /dev/null +++ b/drivers/staging/ktap/scripts/userspace/uprobes-malloc.kp @@ -0,0 +1,9 @@ +#!/usr/bin/env ktap + +trace probe:/lib/libc.so.6:0x000773c0 { + print("entry:", execname(), argevent) +} + +trace probe:/lib/libc.so.6:0x000773c0%return { + print("exit:", execname(), argevent) +} diff --git a/drivers/staging/ktap/test/aggr_table.kp b/drivers/staging/ktap/test/aggr_table.kp new file mode 100644 index 000000000000..985b634952c1 --- /dev/null +++ b/drivers/staging/ktap/test/aggr_table.kp @@ -0,0 +1,50 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +#---------------------------------# + +s = aggr_table() + +s["count"] = count() +s["count"] = count() +s["count"] = count() + +s["max"] = max(1) +s["max"] = max(0) +s["max"] = max(100) + +s["min"] = min(50) +s["min"] = min(2) +s["min"] = min(100) + +s["sum"] = sum(10) +s["sum"] = sum(20) +s["sum"] = sum(30) + +s["avg"] = avg(10) +s["avg"] = avg(20) +s["avg"] = avg(30) + +if (s["count"] != 3) { + failed() +} + +if (s["max"] != 100) { + failed() +} + +if (s["min"] != 2) { + failed() +} + +if (s["sum"] != 60) { + failed() +} + +if (s["avg"] != 20) { + failed() +} diff --git a/drivers/staging/ktap/test/ansi.kp b/drivers/staging/ktap/test/ansi.kp new file mode 100644 index 000000000000..e8a27835ce75 --- /dev/null +++ b/drivers/staging/ktap/test/ansi.kp @@ -0,0 +1,20 @@ +#!/usr/bin/env ktap + +ansi.clear_screen() + +ansi.set_color(32) +printf("this line should be Green color\n") + +ansi.set_color(31) +printf("this line should be Red color\n") + +ansi.set_color2(34, 43) +printf("this line should be Blue color, with Yellow background\n") + +ansi.reset_color() +ansi.set_color3(34, 46, 4) +printf("this line should be Blue color, with Cyan background, underline single attribute\n") + +ansi.reset_color() +ansi.new_line() + diff --git a/drivers/staging/ktap/test/arg.kp b/drivers/staging/ktap/test/arg.kp new file mode 100644 index 000000000000..0cf16ebf3227 --- /dev/null +++ b/drivers/staging/ktap/test/arg.kp @@ -0,0 +1,24 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +#-----------------------------------------# + +if (!arg[0]) { + failed() +} + +if (arg[1] != 1) { + failed() +} + +if (arg[2] != "testing") { + failed() +} + +if (arg[3] != "2 3 4") { + failed() +} diff --git a/drivers/staging/ktap/test/arith.kp b/drivers/staging/ktap/test/arith.kp new file mode 100644 index 000000000000..32880a140c69 --- /dev/null +++ b/drivers/staging/ktap/test/arith.kp @@ -0,0 +1,27 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +#-----------------------------------------# + +a = 4 +b = 5 + +if ((a + b) != 9) { + failed() +} + +if ((a - b) != -1) { + failed() +} + +if ((a % b) != 4) { + failed() +} + +if ((a / b) != 0) { + failed() +} diff --git a/drivers/staging/ktap/test/bench/sembench.c b/drivers/staging/ktap/test/bench/sembench.c new file mode 100644 index 000000000000..08119341c91d --- /dev/null +++ b/drivers/staging/ktap/test/bench/sembench.c @@ -0,0 +1,556 @@ +/* + * copyright Oracle 2007. Licensed under GPLv2 + * To compile: gcc -Wall -o sembench sembench.c -lpthread + * + * usage: sembench -t thread count -w wakenum -r runtime -o op + * op can be: 0 (ipc sem) 1 (nanosleep) 2 (futexes) + * + * example: + * sembench -t 1024 -w 512 -r 60 -o 2 + * runs 1024 threads, waking up 512 at a time, running for 60 seconds using + * futex locking. + * + */ +#define _GNU_SOURCE +#define _POSIX_C_SOURCE 199309 +#include <fcntl.h> +#include <sched.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/sem.h> +#include <sys/ipc.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <pthread.h> +#include <unistd.h> +#include <string.h> +#include <time.h> +#include <sys/time.h> +#include <sys/syscall.h> +#include <errno.h> + +#define VERSION "0.2" + +/* futexes have been around since 2.5.something, but it still seems I + * need to make my own syscall. Sigh. + */ +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_FD 2 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +static inline int futex (int *uaddr, int op, int val, + const struct timespec *timeout, + int *uaddr2, int val3) +{ + return syscall(__NR_futex, uaddr, op, val, timeout, uaddr2, val3); +} + +static void smp_mb(void) +{ + __sync_synchronize(); +} + +static int all_done = 0; +static int timeout_test = 0; + +#define SEMS_PERID 250 + +struct sem_operations; + +struct lockinfo { + unsigned long id; + unsigned long index; + int data; + pthread_t tid; + struct lockinfo *next; + struct sem_operations *ops; + unsigned long ready; +}; + +struct sem_wakeup_info { + int wakeup_count; + struct sembuf sb[SEMS_PERID]; +}; + +struct sem_operations { + void (*wait)(struct lockinfo *l); + int (*wake)(struct sem_wakeup_info *wi, int num_semids, int num); + void (*setup)(struct sem_wakeup_info **wi, int num_semids); + void (*cleanup)(int num_semids); + char *name; +}; + +int *semid_lookup = NULL; + +pthread_mutex_t worklist_mutex = PTHREAD_MUTEX_INITIALIZER; +static unsigned long total_burns = 0; +static unsigned long min_burns = ~0UL; +static unsigned long max_burns = 0; + +/* currently running threads */ +static int thread_count = 0; + +struct lockinfo *worklist = NULL; +static int workers_started = 0; + +/* total threads started */ +static int num_threads = 2048; + +static void worklist_add(struct lockinfo *l) +{ + smp_mb(); + l->ready = 1; +} + +static struct lockinfo *worklist_rm(void) +{ + static int last_index = 0; + int i; + struct lockinfo *l; + + for (i = 0; i < num_threads; i++) { + int test = (last_index + i) % num_threads; + + l = worklist + test; + smp_mb(); + if (l->ready) { + l->ready = 0; + last_index = test; + return l; + } + } + return NULL; +} + +/* ipc semaphore post& wait */ +void wait_ipc_sem(struct lockinfo *l) +{ + struct sembuf sb; + int ret; + struct timespec *tvp = NULL; + struct timespec tv = { 0, 1 }; + + sb.sem_num = l->index; + sb.sem_flg = 0; + + sb.sem_op = -1; + l->data = 1; + + if (timeout_test && (l->id % 5) == 0) + tvp = &tv; + + worklist_add(l); + ret = semtimedop(semid_lookup[l->id], &sb, 1, tvp); + + while(l->data != 0 && tvp) { + struct timespec tv2 = { 0, 500 }; + nanosleep(&tv2, NULL); + } + + if (l->data != 0) { + if (tvp) + return; + fprintf(stderr, "wakeup without data update\n"); + exit(1); + } + if (ret) { + if (errno == EAGAIN && tvp) + return; + perror("semtimed op"); + exit(1); + } +} + +int ipc_wake_some(struct sem_wakeup_info *wi, int num_semids, int num) +{ + int i; + int ret; + struct lockinfo *l; + int found = 0; + + for (i = 0; i < num_semids; i++) { + wi[i].wakeup_count = 0; + } + while(num > 0) { + struct sembuf *sb; + l = worklist_rm(); + if (!l) + break; + if (l->data != 1) + fprintf(stderr, "warning, lockinfo data was %d\n", + l->data); + l->data = 0; + sb = wi[l->id].sb + wi[l->id].wakeup_count; + sb->sem_num = l->index; + sb->sem_op = 1; + sb->sem_flg = IPC_NOWAIT; + wi[l->id].wakeup_count++; + found++; + num--; + } + if (!found) + return 0; + for (i = 0; i < num_semids; i++) { + int wakeup_total; + int cur; + int offset = 0; + if (!wi[i].wakeup_count) + continue; + wakeup_total = wi[i].wakeup_count; + while(wakeup_total > 0) { + cur = wakeup_total > 64 ? 64 : wakeup_total; + ret = semtimedop(semid_lookup[i], wi[i].sb + offset, + cur, NULL); + if (ret) { + perror("semtimedop"); + exit(1); + } + offset += cur; + wakeup_total -= cur; + } + } + return found; +} + +void setup_ipc_sems(struct sem_wakeup_info **wi, int num_semids) +{ + int i; + *wi = malloc(sizeof(**wi) * num_semids); + semid_lookup = malloc(num_semids * sizeof(int)); + for(i = 0; i < num_semids; i++) { + semid_lookup[i] = semget(IPC_PRIVATE, SEMS_PERID, + IPC_CREAT | 0777); + if (semid_lookup[i] < 0) { + perror("semget"); + exit(1); + } + } + sleep(10); +} + +void cleanup_ipc_sems(int num) +{ + int i; + for (i = 0; i < num; i++) { + semctl(semid_lookup[i], 0, IPC_RMID); + } +} + +struct sem_operations ipc_sem_ops = { + .wait = wait_ipc_sem, + .wake = ipc_wake_some, + .setup = setup_ipc_sems, + .cleanup = cleanup_ipc_sems, + .name = "ipc sem operations", +}; + +/* futex post & wait */ +void wait_futex_sem(struct lockinfo *l) +{ + int ret; + l->data = 1; + worklist_add(l); + while(l->data == 1) { + ret = futex(&l->data, FUTEX_WAIT, 1, NULL, NULL, 0); + /* + if (ret && ret != EWOULDBLOCK) { + perror("futex wait"); + exit(1); + }*/ + } +} + +int futex_wake_some(struct sem_wakeup_info *wi, int num_semids, int num) +{ + int i; + int ret; + struct lockinfo *l; + int found = 0; + + for (i = 0; i < num; i++) { + l = worklist_rm(); + if (!l) + break; + if (l->data != 1) + fprintf(stderr, "warning, lockinfo data was %d\n", + l->data); + l->data = 0; + ret = futex(&l->data, FUTEX_WAKE, 1, NULL, NULL, 0); + if (ret < 0) { + perror("futex wake"); + exit(1); + } + found++; + } + return found; +} + +void setup_futex_sems(struct sem_wakeup_info **wi, int num_semids) +{ + return; +} + +void cleanup_futex_sems(int num) +{ + return; +} + +struct sem_operations futex_sem_ops = { + .wait = wait_futex_sem, + .wake = futex_wake_some, + .setup = setup_futex_sems, + .cleanup = cleanup_futex_sems, + .name = "futex sem operations", +}; + +/* nanosleep sems here */ +void wait_nanosleep_sem(struct lockinfo *l) +{ + int ret; + struct timespec tv = { 0, 1000000 }; + int count = 0; + + l->data = 1; + worklist_add(l); + while(l->data) { + ret = nanosleep(&tv, NULL); + if (ret) { + perror("nanosleep"); + exit(1); + } + count++; + } +} + +int nanosleep_wake_some(struct sem_wakeup_info *wi, int num_semids, int num) +{ + int i; + struct lockinfo *l; + + for (i = 0; i < num; i++) { + l = worklist_rm(); + if (!l) + break; + if (l->data != 1) + fprintf(stderr, "warning, lockinfo data was %d\n", + l->data); + l->data = 0; + } + return i; +} + +void setup_nanosleep_sems(struct sem_wakeup_info **wi, int num_semids) +{ + return; +} + +void cleanup_nanosleep_sems(int num) +{ + return; +} + +struct sem_operations nanosleep_sem_ops = { + .wait = wait_nanosleep_sem, + .wake = nanosleep_wake_some, + .setup = setup_nanosleep_sems, + .cleanup = cleanup_nanosleep_sems, + .name = "nano sleep sem operations", +}; + +void *worker(void *arg) +{ + struct lockinfo *l = (struct lockinfo *)arg; + int burn_count = 0; + pthread_t tid = pthread_self(); + size_t pagesize = getpagesize(); + char *buf = malloc(pagesize); + + if (!buf) { + perror("malloc"); + exit(1); + } + + l->tid = tid; + workers_started = 1; + smp_mb(); + + while(!all_done) { + l->ops->wait(l); + if (all_done) + break; + burn_count++; + } + pthread_mutex_lock(&worklist_mutex); + total_burns += burn_count; + if (burn_count < min_burns) + min_burns = burn_count; + if (burn_count > max_burns) + max_burns = burn_count; + thread_count--; + pthread_mutex_unlock(&worklist_mutex); + return (void *)0; +} + +void print_usage(void) +{ + printf("usage: sembench [-t threads] [-w wake incr] [-r runtime]"); + printf(" [-o num] (0=ipc, 1=nanosleep, 2=futex)\n"); + exit(1); +} + +#define NUM_OPERATIONS 3 +struct sem_operations *allops[NUM_OPERATIONS] = { &ipc_sem_ops, + &nanosleep_sem_ops, + &futex_sem_ops}; + +int main(int ac, char **av) { + int ret; + int i; + int semid = 0; + int sem_num = 0; + int burn_count = 0; + struct sem_wakeup_info *wi = NULL; + struct timeval start; + struct timeval now; + int num_semids = 0; + int wake_num = 256; + int run_secs = 30; + int pagesize = getpagesize(); + char *buf = malloc(pagesize); + struct sem_operations *ops = allops[0]; + cpu_set_t cpu_mask; + cpu_set_t target_mask; + int target_cpu = 0; + int max_cpu = -1; + + if (!buf) { + perror("malloc"); + exit(1); + } + for (i = 1; i < ac; i++) { + if (strcmp(av[i], "-t") == 0) { + if (i == ac -1) + print_usage(); + num_threads = atoi(av[i+1]); + i++; + } else if (strcmp(av[i], "-w") == 0) { + if (i == ac -1) + print_usage(); + wake_num = atoi(av[i+1]); + i++; + } else if (strcmp(av[i], "-r") == 0) { + if (i == ac -1) + print_usage(); + run_secs = atoi(av[i+1]); + i++; + } else if (strcmp(av[i], "-o") == 0) { + int index; + if (i == ac -1) + print_usage(); + index = atoi(av[i+1]); + if (index >= NUM_OPERATIONS) { + fprintf(stderr, "invalid operations %d\n", + index); + exit(1); + } + ops = allops[index]; + i++; + } else if (strcmp(av[i], "-T") == 0) { + timeout_test = 1; + } else if (strcmp(av[i], "-h") == 0) { + print_usage(); + } + } + num_semids = (num_threads + SEMS_PERID - 1) / SEMS_PERID; + ops->setup(&wi, num_semids); + + ret = sched_getaffinity(0, sizeof(cpu_set_t), &cpu_mask); + if (ret) { + perror("sched_getaffinity"); + exit(1); + } + for (i = 0; i < CPU_SETSIZE; i++) + if (CPU_ISSET(i, &cpu_mask)) + max_cpu = i; + if (max_cpu == -1) { + fprintf(stderr, "sched_getaffinity returned empty mask\n"); + exit(1); + } + + CPU_ZERO(&target_mask); + + worklist = malloc(sizeof(*worklist) * num_threads); + memset(worklist, 0, sizeof(*worklist) * num_threads); + + for (i = 0; i < num_threads; i++) { + struct lockinfo *l; + pthread_t tid; + thread_count++; + l = worklist + i; + if (!l) { + perror("malloc"); + exit(1); + } + l->id = semid; + l->index = sem_num++; + l->ops = ops; + if (sem_num >= SEMS_PERID) { + semid++; + sem_num = 0; + } + ret = pthread_create(&tid, NULL, worker, (void *)l); + if (ret) { + perror("pthread_create"); + exit(1); + } + + while (!CPU_ISSET(target_cpu, &cpu_mask)) { + target_cpu++; + if (target_cpu > max_cpu) + target_cpu = 0; + } + CPU_SET(target_cpu, &target_mask); + ret = pthread_setaffinity_np(tid, sizeof(cpu_set_t), + &target_mask); + CPU_CLR(target_cpu, &target_mask); + target_cpu++; + + ret = pthread_detach(tid); + if (ret) { + perror("pthread_detach"); + exit(1); + } + } + while(!workers_started) { + smp_mb(); + usleep(200); + } + gettimeofday(&start, NULL); + fprintf(stderr, "main loop going\n"); + while(1) { + ops->wake(wi, num_semids, wake_num); + burn_count++; + gettimeofday(&now, NULL); + if (now.tv_sec - start.tv_sec >= run_secs) + break; + } + fprintf(stderr, "all done\n"); + all_done = 1; + while(thread_count > 0) { + ops->wake(wi, num_semids, wake_num); + usleep(200); + } + printf("%d threads, waking %d at a time\n", num_threads, wake_num); + printf("using %s\n", ops->name); + printf("main thread burns: %d\n", burn_count); + printf("worker burn count total %lu min %lu max %lu avg %lu\n", + total_burns, min_burns, max_burns, total_burns / num_threads); + printf("run time %d seconds %lu worker burns per second\n", + (int)(now.tv_sec - start.tv_sec), + total_burns / (now.tv_sec - start.tv_sec)); + ops->cleanup(num_semids); + return 0; +} + diff --git a/drivers/staging/ktap/test/bench/test.sh b/drivers/staging/ktap/test/bench/test.sh new file mode 100644 index 000000000000..9f77969b6f2b --- /dev/null +++ b/drivers/staging/ktap/test/bench/test.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +gcc -o sembench sembench.c -O2 -lpthread + +COMMAND="./sembench -t 200 -w 20 -r 30 -o 2" + +echo -e "\n\t\tPass 1 without tracing" +$COMMAND +echo -e "\n\t\tPass 2 without tracing" +$COMMAND +echo -e "\n\t\tPass 3 without tracing" +$COMMAND + +echo "" + +KTAP_ONE_LINER="trace syscalls:sys_*_futex {}" + +echo -e "\n\t\tPass 1 with tracing" +../../ktap -e "$KTAP_ONE_LINER" -- $COMMAND +echo -e "\n\t\tPass 2 with tracing" +../../ktap -e "$KTAP_ONE_LINER" -- $COMMAND +echo -e "\n\t\tPass 3 with tracing" +../../ktap -e "$KTAP_ONE_LINER" -- $COMMAND + +rm -rf ./sembench diff --git a/drivers/staging/ktap/test/concat.kp b/drivers/staging/ktap/test/concat.kp new file mode 100644 index 000000000000..be77bb70ea8e --- /dev/null +++ b/drivers/staging/ktap/test/concat.kp @@ -0,0 +1,15 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +#----------------------------------------# + +a = "123" +b = "456" + +if (a..b != "123456") { + failed() +} diff --git a/drivers/staging/ktap/test/count.kp b/drivers/staging/ktap/test/count.kp new file mode 100644 index 000000000000..26f962c227a4 --- /dev/null +++ b/drivers/staging/ktap/test/count.kp @@ -0,0 +1,20 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +#---------------------------------------# + +t = {} + +t["key"] += 1 +if (t["key"] != 1) { + failed() +} + +t["key"] += 1 +if (t["key"] != 2) { + failed() +} diff --git a/drivers/staging/ktap/test/fibonacci.kp b/drivers/staging/ktap/test/fibonacci.kp new file mode 100644 index 000000000000..7e141da0de42 --- /dev/null +++ b/drivers/staging/ktap/test/fibonacci.kp @@ -0,0 +1,36 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +#---------------fibonacci---------------- + + +#regular recursive fibonacci +function fib(n) { + if (n < 2) { + return n + } + return fib(n-1) + fib(n-2) +} + +if (fib(20) != 6765) { + failed() +} + +#tail recursive fibonacci +function fib(n) { + f = function (iter, res, next) { + if (iter == 0) { + return res; + } + return f(iter-1, next, res+next) + } + return f(n, 0, 1) +} + +if (fib(20) != 6765) { + failed() +} diff --git a/drivers/staging/ktap/test/function.kp b/drivers/staging/ktap/test/function.kp new file mode 100644 index 000000000000..bfbff2614104 --- /dev/null +++ b/drivers/staging/ktap/test/function.kp @@ -0,0 +1,88 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +### basic function call ### +function f1(a, b) { + return a + b +} + +if (f1(2, 3) != 5) { + failed(); +} + +### return string ### +function f2() { + return "function return" +} + +if (f2() != "function return") { + failed(); +} + +### mutli-value return ### +function f3(a, b) { + return a+b, a-b; +} + +c, d = f3(2, 3); +if(c != 5 || d != -1) { + failed(); +} + + +### closure testing ### +function f4() { + f5 = function(a, b) { + return a * b + } + return f5 +} + +local f = f4() +if (f(9, 9) != 81) { + failed(); +} + +### closure with lexcial variable ### +# issue: variable cannot be local +i = 1 +function f6() { + i = 5 + f7 = function(a, b) { + return a * b + i + } + return f7 +} + +f = f6() +if (f(9, 9) != 81 + i) { + failed(); +} + +i = 6 +if (f(9, 9) != 81 + i) { + failed(); +} + +### tail call +### stack should not overflow in tail call mechanism +a = 0 +function f8(i) { + if (i == 1000000) { + a = 1000000 + return + } + # must add return here, otherwise stack overflow + return f8(i+1) +} + +f8(0) +if (a != 1000000) { + failed(); +} + + diff --git a/drivers/staging/ktap/test/if.kp b/drivers/staging/ktap/test/if.kp new file mode 100644 index 000000000000..3122084af5ee --- /dev/null +++ b/drivers/staging/ktap/test/if.kp @@ -0,0 +1,24 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +#-----------------------------------------# + +if (false) { + failed() +} + +if (nil) { + failed() +} + +# ktap only think false and nil is "real false", number 0 is true +# it's same as lua +# Might change it in future, to make similar with C +if (0) { + #failed() +} + diff --git a/drivers/staging/ktap/test/kprobe.kp b/drivers/staging/ktap/test/kprobe.kp new file mode 100644 index 000000000000..022d4a70b31f --- /dev/null +++ b/drivers/staging/ktap/test/kprobe.kp @@ -0,0 +1,14 @@ +#!/usr/bin/env ktap + +n = 0 +trace probe:schedule { + n = n + 1 +} + +tick-1s { + if (n == 0) { + printf("failed\n"); + } + exit() +} + diff --git a/drivers/staging/ktap/test/kretprobe.kp b/drivers/staging/ktap/test/kretprobe.kp new file mode 100644 index 000000000000..e311e84c292f --- /dev/null +++ b/drivers/staging/ktap/test/kretprobe.kp @@ -0,0 +1,14 @@ +#!/usr/bin/env ktap + +n = 0 +trace probe:__schedule%return { + n = n + 1 +} + +tick-1s { + if (n == 0) { + printf("failed\n"); + } + exit() +} + diff --git a/drivers/staging/ktap/test/len.kp b/drivers/staging/ktap/test/len.kp new file mode 100644 index 000000000000..697d91553ba9 --- /dev/null +++ b/drivers/staging/ktap/test/len.kp @@ -0,0 +1,25 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +#-----------------------------------------# + +a = "123456789" + +if (len(a) != 9) { + failed() +} + +b = {} +b[0] = 0 +b[1] = 1 +b["keys"] = "values" + +if (len(b) != 3) { + failed() +} + + diff --git a/drivers/staging/ktap/test/looping.kp b/drivers/staging/ktap/test/looping.kp new file mode 100644 index 000000000000..fe48051a29c2 --- /dev/null +++ b/drivers/staging/ktap/test/looping.kp @@ -0,0 +1,40 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +### basic while-loop testing +a = 1 +while (a < 1000) { + a = a + 1 +} + +if (a != 1000) { + failed() +} + +### break testing +### Note that ktap don't have continue keyword +a = 1 +while (a < 1000) { + if (a == 10) { + break + } + a = a + 1 +} + +if (a != 10) { + failed() +} + +### for-loop testing +b=0 +for (c = 0, 1000, 1) { + b = b + 1 +} + +if (b != 1001) { + failed() +} diff --git a/drivers/staging/ktap/test/pairs.kp b/drivers/staging/ktap/test/pairs.kp new file mode 100644 index 000000000000..cdf3825951dd --- /dev/null +++ b/drivers/staging/ktap/test/pairs.kp @@ -0,0 +1,45 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +#-----------------------------------------# + +t = {} +t[1] = 101 +t[2] = 102 +t[3] = 103 +t["key_1"] = "value_1" +t["key_2"] = "value_2" +t["key_3"] = "value_3" + +local n = 0 + +for (k, v in pairs(t)) { + n = n + 1 + + if (k == 1 && v != 101) { + failed() + } + if (k == 2 && v != 102) { + failed() + } + if (k == 3 && v != 103) { + failed() + } + if (k == "key_1" && v != "value_1") { + failed() + } + if (k == "key_2" && v != "value_2") { + failed() + } + if (k == "key_3" && v != "value_3") { + failed() + } +} + +if (n != len(t)) { + failed() +} diff --git a/drivers/staging/ktap/test/run_test.sh b/drivers/staging/ktap/test/run_test.sh new file mode 100644 index 000000000000..b98af2659123 --- /dev/null +++ b/drivers/staging/ktap/test/run_test.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +rmmod ktapvm > /dev/null 2>&1 +insmod ../ktapvm.ko +if test $? -ne 0; then + echo "Cannot insmod ../ktapvm.ko" + exit -1 +fi + +KTAP=../ktap +function ktaprun { + echo "$KTAP $@" + $KTAP $@ +} + + + +####################################################### +# Use $ktap directly if the arguments contains strings +$KTAP arg.kp 1 testing "2 3 4" +$KTAP -e 'print("one-liner testing")' +$KTAP -e 'exit()' +$KTAP -o /dev/null -e 'trace syscalls:* { print(argevent) }' \ + -- ls > /devnull + +$KTAP -o /dev/null -e 'trace syscalls:* { print(argevent) }' \ + -- $KTAP -e 'while (1) {}' + +ktaprun arith.kp +ktaprun concat.kp +ktaprun count.kp +ktaprun fibonacci.kp +ktaprun function.kp +ktaprun if.kp +ktaprun kprobe.kp +ktaprun kretprobe.kp +ktaprun len.kp +ktaprun looping.kp +ktaprun pairs.kp +ktaprun table.kp +ktaprun aggr_table.kp +ktaprun timer.kp +ktaprun tracepoint.kp +ktaprun -o /dev/null zerodivide.kp +ktaprun ansi.kp + +echo "testing kill deadloop ktap script" +$KTAP -e 'while (1) {}' & +pkill ktap +sleep 1 + +##################################################### +rmmod ktapvm +if test $? -ne 0; then + echo "Error in rmmod ../ktapvm.ko, leak module refcount?" + exit -1 +fi + diff --git a/drivers/staging/ktap/test/table.kp b/drivers/staging/ktap/test/table.kp new file mode 100644 index 000000000000..1f6d6e43302f --- /dev/null +++ b/drivers/staging/ktap/test/table.kp @@ -0,0 +1,71 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +### table testing ### +x = {} +x[1] = "1" +if (x[1] != "1") { + failed() +} + +x[1] = 22222222222222222222222222222222222222222 +if (x[1] != 22222222222222222222222222222222222222222) { + failed() +} + +x[1] = "jovi" +if (x[1] != "jovi") { + failed() +} + +x[11111111111111111111111111111111] = "jovi" +if (x[11111111111111111111111111111111] != "jovi") { + failed() +} + +x["jovi"] = 1 +if (x["jovi"] != 1) { + failed() +} + +x["long string....................................."] = 1 +if (x["long string....................................."] != 1) { + failed() +} + +# issue: subx must declare firstly, otherwise kernel will oops +subx = {} +subx["test"] = "this is test" +x["test"] = subx +if (x["test"]["test"] != "this is test") { + failed() +} + +tbl = {} +i = 1 +while (i < 100000) { + tbl[i] = i + i = i + 1 +} + +i = 1 +while (i < 100000) { + if (tbl[i] != i) { + failed() + } + i = i + 1 +} + +#### table initization +days = {"Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday"} + +if (days[2] != "Monday") { + failed() +} + + diff --git a/drivers/staging/ktap/test/timer.kp b/drivers/staging/ktap/test/timer.kp new file mode 100644 index 000000000000..02e8a61da664 --- /dev/null +++ b/drivers/staging/ktap/test/timer.kp @@ -0,0 +1,28 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +#---------------------------------------# + +n1 = 0 +n2 = 0 + +tick-1s { + n1 = n1 + 1 +} + +tick-1s { + n2 = n2 + 1 +} + +tick-4s { + if (n1 == 0 || n2 == 0) { + failed() + } + exit() +} + + diff --git a/drivers/staging/ktap/test/tracepoint.kp b/drivers/staging/ktap/test/tracepoint.kp new file mode 100644 index 000000000000..fb036e675a75 --- /dev/null +++ b/drivers/staging/ktap/test/tracepoint.kp @@ -0,0 +1,22 @@ +#!/usr/bin/env ktap + +function failed() { + printf("failed\n"); + exit(-1); +} + +#----------------------------------------# + +n = 0 + +trace sched:* { + n = n + 1 +} + +tick-1s { + if (n == 0) { + failed() + } + exit() +} + diff --git a/drivers/staging/ktap/test/zerodivide.kp b/drivers/staging/ktap/test/zerodivide.kp new file mode 100644 index 000000000000..abb1eae4fdab --- /dev/null +++ b/drivers/staging/ktap/test/zerodivide.kp @@ -0,0 +1,5 @@ +#!/usr/bin/env ktap + +a = 1/0 +#should not go here +printf("Failed\n") diff --git a/drivers/staging/ktap/userspace/code.c b/drivers/staging/ktap/userspace/code.c new file mode 100644 index 000000000000..1427fd518dec --- /dev/null +++ b/drivers/staging/ktap/userspace/code.c @@ -0,0 +1,968 @@ +/* + * code.c - Code generator for ktap + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * Copyright (C) 1994-2013 Lua.org, PUC-Rio. + * - The part of code in this file is copied from lua initially. + * - lua's MIT license is compatible with GPL. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../include/ktap_types.h" +#include "../include/ktap_opcodes.h" +#include "ktapc.h" + + +#define hasjumps(e) ((e)->t != (e)->f) + +void codegen_patchtohere (ktap_funcstate *fs, int list); + +static int isnumeral(ktap_expdesc *e) +{ + return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); +} + +void codegen_nil(ktap_funcstate *fs, int from, int n) +{ + ktap_instruction *previous; + int l = from + n - 1; /* last register to set nil */ + + if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ + previous = &fs->f->code[fs->pc-1]; + if (GET_OPCODE(*previous) == OP_LOADNIL) { + int pfrom = GETARG_A(*previous); + int pl = pfrom + GETARG_B(*previous); + + if ((pfrom <= from && from <= pl + 1) || + (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ + if (pfrom < from) + from = pfrom; /* from = min(from, pfrom) */ + if (pl > l) + l = pl; /* l = max(l, pl) */ + SETARG_A(*previous, from); + SETARG_B(*previous, l - from); + return; + } + } /* else go through */ + } + codegen_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ +} + +int codegen_jump(ktap_funcstate *fs) +{ + int jpc = fs->jpc; /* save list of jumps to here */ + int j; + + fs->jpc = NO_JUMP; + j = codegen_codeAsBx(fs, OP_JMP, 0, NO_JUMP); + codegen_concat(fs, &j, jpc); /* keep them on hold */ + return j; +} + +void codegen_ret(ktap_funcstate *fs, int first, int nret) +{ + codegen_codeABC(fs, OP_RETURN, first, nret+1, 0); +} + +static int condjump(ktap_funcstate *fs, OpCode op, int A, int B, int C) +{ + codegen_codeABC(fs, op, A, B, C); + return codegen_jump(fs); +} + +static void fixjump(ktap_funcstate *fs, int pc, int dest) +{ + ktap_instruction *jmp = &fs->f->code[pc]; + int offset = dest-(pc+1); + + ktap_assert(dest != NO_JUMP); + if (abs(offset) > MAXARG_sBx) + lex_syntaxerror(fs->ls, "control structure too long"); + SETARG_sBx(*jmp, offset); +} + +/* + * returns current `pc' and marks it as a jump target (to avoid wrong + * optimizations with consecutive instructions not in the same basic block). + */ +int codegen_getlabel(ktap_funcstate *fs) +{ + fs->lasttarget = fs->pc; + return fs->pc; +} + +static int getjump(ktap_funcstate *fs, int pc) +{ + int offset = GETARG_sBx(fs->f->code[pc]); + + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc+1)+offset; /* turn offset into absolute position */ +} + +static ktap_instruction *getjumpcontrol(ktap_funcstate *fs, int pc) +{ + ktap_instruction *pi = &fs->f->code[pc]; + if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) + return pi-1; + else + return pi; +} + +/* + * check whether list has any jump that do not produce a value + * (or produce an inverted value) + */ +static int need_value(ktap_funcstate *fs, int list) +{ + for (; list != NO_JUMP; list = getjump(fs, list)) { + ktap_instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TESTSET) + return 1; + } + return 0; /* not found */ +} + +static int patchtestreg(ktap_funcstate *fs, int node, int reg) +{ + ktap_instruction *i = getjumpcontrol(fs, node); + if (GET_OPCODE(*i) != OP_TESTSET) + return 0; /* cannot patch other instructions */ + if (reg != NO_REG && reg != GETARG_B(*i)) + SETARG_A(*i, reg); + else /* no register to put value or register already has the value */ + *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); + + return 1; +} + +static void removevalues(ktap_funcstate *fs, int list) +{ + for (; list != NO_JUMP; list = getjump(fs, list)) + patchtestreg(fs, list, NO_REG); +} + +static void patchlistaux(ktap_funcstate *fs, int list, int vtarget, int reg, + int dtarget) +{ + while (list != NO_JUMP) { + int next = getjump(fs, list); + if (patchtestreg(fs, list, reg)) + fixjump(fs, list, vtarget); + else + fixjump(fs, list, dtarget); /* jump to default target */ + list = next; + } +} + +static void dischargejpc(ktap_funcstate *fs) +{ + patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); + fs->jpc = NO_JUMP; +} + +void codegen_patchlist(ktap_funcstate *fs, int list, int target) +{ + if (target == fs->pc) + codegen_patchtohere(fs, list); + else { + ktap_assert(target < fs->pc); + patchlistaux(fs, list, target, NO_REG, target); + } +} + +void codegen_patchclose(ktap_funcstate *fs, int list, int level) +{ + level++; /* argument is +1 to reserve 0 as non-op */ + while (list != NO_JUMP) { + int next = getjump(fs, list); + ktap_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && + (GETARG_A(fs->f->code[list]) == 0 || + GETARG_A(fs->f->code[list]) >= level)); + SETARG_A(fs->f->code[list], level); + list = next; + } +} + +void codegen_patchtohere(ktap_funcstate *fs, int list) +{ + codegen_getlabel(fs); + codegen_concat(fs, &fs->jpc, list); +} + +void codegen_concat(ktap_funcstate *fs, int *l1, int l2) +{ + if (l2 == NO_JUMP) + return; + else if (*l1 == NO_JUMP) + *l1 = l2; + else { + int list = *l1; + int next; + while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + fixjump(fs, list, l2); + } +} + +static int codegen_code(ktap_funcstate *fs, ktap_instruction i) +{ + ktap_proto *f = fs->f; + + dischargejpc(fs); /* `pc' will change */ + + /* put new instruction in code array */ + ktapc_growvector(f->code, fs->pc, f->sizecode, ktap_instruction, + MAX_INT, "opcodes"); + f->code[fs->pc] = i; + + /* save corresponding line information */ + ktapc_growvector(f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "opcodes"); + f->lineinfo[fs->pc] = fs->ls->lastline; + return fs->pc++; +} + +int codegen_codeABC(ktap_funcstate *fs, OpCode o, int a, int b, int c) +{ + ktap_assert(getOpMode(o) == iABC); + //ktap_assert(getBMode(o) != OpArgN || b == 0); + //ktap_assert(getCMode(o) != OpArgN || c == 0); + //ktap_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); + return codegen_code(fs, CREATE_ABC(o, a, b, c)); +} + +int codegen_codeABx(ktap_funcstate *fs, OpCode o, int a, unsigned int bc) +{ + ktap_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); + ktap_assert(getCMode(o) == OpArgN); + ktap_assert(a <= MAXARG_A && bc <= MAXARG_Bx); + return codegen_code(fs, CREATE_ABx(o, a, bc)); +} + +static int codeextraarg(ktap_funcstate *fs, int a) +{ + ktap_assert(a <= MAXARG_Ax); + return codegen_code(fs, CREATE_Ax(OP_EXTRAARG, a)); +} + +int codegen_codek(ktap_funcstate *fs, int reg, int k) +{ + if (k <= MAXARG_Bx) + return codegen_codeABx(fs, OP_LOADK, reg, k); + else { + int p = codegen_codeABx(fs, OP_LOADKX, reg, 0); + codeextraarg(fs, k); + return p; + } +} + +void codegen_checkstack(ktap_funcstate *fs, int n) +{ + int newstack = fs->freereg + n; + + if (newstack > fs->f->maxstacksize) { + if (newstack >= MAXSTACK) + lex_syntaxerror(fs->ls, "function or expression too complex"); + fs->f->maxstacksize = (u8)(newstack); + } +} + +void codegen_reserveregs(ktap_funcstate *fs, int n) +{ + codegen_checkstack(fs, n); + fs->freereg += n; +} + +static void freereg(ktap_funcstate *fs, int reg) +{ + if (!ISK(reg) && reg >= fs->nactvar) { + fs->freereg--; + ktap_assert(reg == fs->freereg); + } +} + +static void freeexp(ktap_funcstate *fs, ktap_expdesc *e) +{ + if (e->k == VNONRELOC) + freereg(fs, e->u.info); +} + +static int addk(ktap_funcstate *fs, ktap_value *key, ktap_value *v) +{ + const ktap_value *idx = ktapc_table_get(fs->h, key); + ktap_proto *f = fs->f; + ktap_value kn; + int k, oldsize; + + if (ttisnumber(idx)) { + ktap_number n = nvalue(idx); + ktap_number2int(k, n); + if (ktapc_equalobj(&f->k[k], v)) + return k; + /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); + go through and create a new entry for this value */ + } + /* constant not found; create a new entry */ + oldsize = f->sizek; + k = fs->nk; + + /* numerical value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setnvalue(&kn, (ktap_number)k); + ktapc_table_setvalue(fs->h, key, &kn); + ktapc_growvector(f->k, k, f->sizek, ktap_value, MAXARG_Ax, "constants"); + while (oldsize < f->sizek) + setnilvalue(&f->k[oldsize++]); + setobj(&f->k[k], v); + fs->nk++; + return k; +} + +int codegen_stringK(ktap_funcstate *fs, ktap_string *s) +{ + ktap_value o; + + setsvalue(&o, s); + return addk(fs, &o, &o); +} + +int codegen_numberK(ktap_funcstate *fs, ktap_number r) +{ + int n; + ktap_value o, s; + + setnvalue(&o, r); + if (r == 0 || ktap_numisnan(NULL, r)) { /* handle -0 and NaN */ + /* use raw representation as key to avoid numeric problems */ + setsvalue(&s, ktapc_ts_newlstr((char *)&r, sizeof(r))); + // incr_top(L); + n = addk(fs, &s, &o); + // L->top--; + } else + n = addk(fs, &o, &o); /* regular case */ + return n; +} + +static int boolK(ktap_funcstate *fs, int b) +{ + ktap_value o; + setbvalue(&o, b); + return addk(fs, &o, &o); +} + +static int nilK(ktap_funcstate *fs) +{ + ktap_value k, v; + setnilvalue(&v); + /* cannot use nil as key; instead use table itself to represent nil */ + sethvalue(&k, fs->h); + return addk(fs, &k, &v); +} + +void codegen_setreturns(ktap_funcstate *fs, ktap_expdesc *e, int nresults) +{ + if (e->k == VCALL) { /* expression is an open function call? */ + SETARG_C(getcode(fs, e), nresults+1); + } + else if (e->k == VVARARG) { + SETARG_B(getcode(fs, e), nresults+1); + SETARG_A(getcode(fs, e), fs->freereg); + codegen_reserveregs(fs, 1); + } +} + +void codegen_setoneret(ktap_funcstate *fs, ktap_expdesc *e) +{ + if (e->k == VCALL) { /* expression is an open function call? */ + e->k = VNONRELOC; + e->u.info = GETARG_A(getcode(fs, e)); + } else if (e->k == VVARARG) { + SETARG_B(getcode(fs, e), 2); + e->k = VRELOCABLE; /* can relocate its simple result */ + } +} + +void codegen_dischargevars(ktap_funcstate *fs, ktap_expdesc *e) +{ + switch (e->k) { + case VLOCAL: { + e->k = VNONRELOC; + break; + } + case VUPVAL: { + e->u.info = codegen_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); + e->k = VRELOCABLE; + break; + } + case VINDEXED: { + OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ + freereg(fs, e->u.ind.idx); + if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ + freereg(fs, e->u.ind.t); + op = OP_GETTABLE; + } + e->u.info = codegen_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOCABLE; + break; + } + case VVARARG: + case VCALL: { + codegen_setoneret(fs, e); + break; + } + default: + break; /* there is one value available (somewhere) */ + } +} + +static int code_label(ktap_funcstate *fs, int A, int b, int jump) +{ + codegen_getlabel(fs); /* those instructions may be jump targets */ + return codegen_codeABC(fs, OP_LOADBOOL, A, b, jump); +} + +static void discharge2reg(ktap_funcstate *fs, ktap_expdesc *e, int reg) +{ + codegen_dischargevars(fs, e); + switch (e->k) { + case VNIL: { + codegen_nil(fs, reg, 1); + break; + } + case VFALSE: case VTRUE: { + codegen_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); + break; + } + case VEVENT: + codegen_codeABC(fs, OP_EVENT, reg, 0, 0); + break; + case VEVENTNAME: + codegen_codeABC(fs, OP_EVENTNAME, reg, 0, 0); + break; + case VEVENTARG: + codegen_codeABC(fs, OP_EVENTARG, reg, e->u.info, 0); + break; + case VK: { + codegen_codek(fs, reg, e->u.info); + break; + } + case VKNUM: { + codegen_codek(fs, reg, codegen_numberK(fs, e->u.nval)); + break; + } + case VRELOCABLE: { + ktap_instruction *pc = &getcode(fs, e); + SETARG_A(*pc, reg); + break; + } + case VNONRELOC: { + if (reg != e->u.info) + codegen_codeABC(fs, OP_MOVE, reg, e->u.info, 0); + break; + } + default: + ktap_assert(e->k == VVOID || e->k == VJMP); + return; /* nothing to do... */ + } + + e->u.info = reg; + e->k = VNONRELOC; +} + +static void discharge2anyreg(ktap_funcstate *fs, ktap_expdesc *e) +{ + if (e->k != VNONRELOC) { + codegen_reserveregs(fs, 1); + discharge2reg(fs, e, fs->freereg-1); + } +} + +static void exp2reg(ktap_funcstate *fs, ktap_expdesc *e, int reg) +{ + discharge2reg(fs, e, reg); + if (e->k == VJMP) + codegen_concat(fs, &e->t, e->u.info); /* put this jump in `t' list */ + if (hasjumps(e)) { + int final; /* position after whole expression */ + int p_f = NO_JUMP; /* position of an eventual LOAD false */ + int p_t = NO_JUMP; /* position of an eventual LOAD true */ + + if (need_value(fs, e->t) || need_value(fs, e->f)) { + int fj = (e->k == VJMP) ? NO_JUMP : codegen_jump(fs); + + p_f = code_label(fs, reg, 0, 1); + p_t = code_label(fs, reg, 1, 0); + codegen_patchtohere(fs, fj); + } + final = codegen_getlabel(fs); + patchlistaux(fs, e->f, final, reg, p_f); + patchlistaux(fs, e->t, final, reg, p_t); + } + e->f = e->t = NO_JUMP; + e->u.info = reg; + e->k = VNONRELOC; +} + +void codegen_exp2nextreg(ktap_funcstate *fs, ktap_expdesc *e) +{ + codegen_dischargevars(fs, e); + freeexp(fs, e); + codegen_reserveregs(fs, 1); + exp2reg(fs, e, fs->freereg - 1); +} + +int codegen_exp2anyreg(ktap_funcstate *fs, ktap_expdesc *e) +{ + codegen_dischargevars(fs, e); + if (e->k == VNONRELOC) { + if (!hasjumps(e)) + return e->u.info; /* exp is already in a register */ + if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ + exp2reg(fs, e, e->u.info); /* put value on it */ + return e->u.info; + } + } + codegen_exp2nextreg(fs, e); /* default */ + return e->u.info; +} + +void codegen_exp2anyregup(ktap_funcstate *fs, ktap_expdesc *e) +{ + if (e->k != VUPVAL || hasjumps(e)) + codegen_exp2anyreg(fs, e); +} + +void codegen_exp2val(ktap_funcstate *fs, ktap_expdesc *e) +{ + if (hasjumps(e)) + codegen_exp2anyreg(fs, e); + else + codegen_dischargevars(fs, e); +} + +int codegen_exp2RK(ktap_funcstate *fs, ktap_expdesc *e) +{ + codegen_exp2val(fs, e); + switch (e->k) { + case VTRUE: + case VFALSE: + case VNIL: { + if (fs->nk <= MAXINDEXRK) { /* constant fits in RK operand? */ + e->u.info = (e->k == VNIL) ? nilK(fs) : + boolK(fs, (e->k == VTRUE)); + e->k = VK; + return RKASK(e->u.info); + } + else + break; + } + case VKNUM: { + e->u.info = codegen_numberK(fs, e->u.nval); + e->k = VK; + /* go through */ + } + case VK: { + if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */ + return RKASK(e->u.info); + else + break; + } + default: + break; + } + /* not a constant in the right range: put it in a register */ + return codegen_exp2anyreg(fs, e); +} + +void codegen_storevar(ktap_funcstate *fs, ktap_expdesc *var, ktap_expdesc *ex) +{ + switch (var->k) { + case VLOCAL: { + freeexp(fs, ex); + exp2reg(fs, ex, var->u.info); + return; + } + case VUPVAL: { + int e = codegen_exp2anyreg(fs, ex); + codegen_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); + break; + } + case VINDEXED: { + OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; + int e = codegen_exp2RK(fs, ex); + codegen_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); + break; + } + default: + ktap_assert(0); /* invalid var kind to store */ + break; + } + + freeexp(fs, ex); +} + +void codegen_storeincr(ktap_funcstate *fs, ktap_expdesc *var, ktap_expdesc *ex) +{ + switch (var->k) { +#if 0 /*current not supported */ + case VLOCAL: { + freeexp(fs, ex); + exp2reg(fs, ex, var->u.info); + return; + } + case VUPVAL: { + int e = codegen_exp2anyreg(fs, ex); + codegen_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); + break; + } +#endif + case VINDEXED: { + OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE_INCR : + OP_SETTABUP_INCR; + int e = codegen_exp2RK(fs, ex); + codegen_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); + break; + } + default: + ktap_assert(0); /* invalid var kind to store */ + break; + } + + freeexp(fs, ex); +} + + +void codegen_self(ktap_funcstate *fs, ktap_expdesc *e, ktap_expdesc *key) +{ + int ereg; + + codegen_exp2anyreg(fs, e); + ereg = e->u.info; /* register where 'e' was placed */ + freeexp(fs, e); + e->u.info = fs->freereg; /* base register for op_self */ + e->k = VNONRELOC; + codegen_reserveregs(fs, 2); /* function and 'self' produced by op_self */ + codegen_codeABC(fs, OP_SELF, e->u.info, ereg, codegen_exp2RK(fs, key)); + freeexp(fs, key); +} + +static void invertjump(ktap_funcstate *fs, ktap_expdesc *e) +{ + ktap_instruction *pc = getjumpcontrol(fs, e->u.info); + ktap_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && + GET_OPCODE(*pc) != OP_TEST); + SETARG_A(*pc, !(GETARG_A(*pc))); +} + +static int jumponcond(ktap_funcstate *fs, ktap_expdesc *e, int cond) +{ + if (e->k == VRELOCABLE) { + ktap_instruction ie = getcode(fs, e); + if (GET_OPCODE(ie) == OP_NOT) { + fs->pc--; /* remove previous OP_NOT */ + return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); + } + /* else go through */ + } + discharge2anyreg(fs, e); + freeexp(fs, e); + return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); +} + +void codegen_goiftrue(ktap_funcstate *fs, ktap_expdesc *e) +{ + int pc; /* pc of last jump */ + + codegen_dischargevars(fs, e); + switch (e->k) { + case VJMP: { + invertjump(fs, e); + pc = e->u.info; + break; + } + case VK: case VKNUM: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } + default: + pc = jumponcond(fs, e, 0); + break; + } + + codegen_concat(fs, &e->f, pc); /* insert last jump in `f' list */ + codegen_patchtohere(fs, e->t); + e->t = NO_JUMP; +} + +void codegen_goiffalse(ktap_funcstate *fs, ktap_expdesc *e) +{ + int pc; /* pc of last jump */ + codegen_dischargevars(fs, e); + + switch (e->k) { + case VJMP: { + pc = e->u.info; + break; + } + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ + break; + } + default: + pc = jumponcond(fs, e, 1); + break; + } + codegen_concat(fs, &e->t, pc); /* insert last jump in `t' list */ + codegen_patchtohere(fs, e->f); + e->f = NO_JUMP; +} + +static void codenot(ktap_funcstate *fs, ktap_expdesc *e) +{ + codegen_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + e->k = VTRUE; + break; + } + case VK: case VKNUM: case VTRUE: { + e->k = VFALSE; + break; + } + case VJMP: { + invertjump(fs, e); + break; + } + case VRELOCABLE: + case VNONRELOC: { + discharge2anyreg(fs, e); + freeexp(fs, e); + e->u.info = codegen_codeABC(fs, OP_NOT, 0, e->u.info, 0); + e->k = VRELOCABLE; + break; + } + default: + ktap_assert(0); /* cannot happen */ + break; + } + + /* interchange true and false lists */ + { int temp = e->f; e->f = e->t; e->t = temp; } + removevalues(fs, e->f); + removevalues(fs, e->t); +} + +void codegen_indexed(ktap_funcstate *fs, ktap_expdesc *t, ktap_expdesc *k) +{ + ktap_assert(!hasjumps(t)); + t->u.ind.t = t->u.info; + t->u.ind.idx = codegen_exp2RK(fs, k); + t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL + : check_exp(vkisinreg(t->k), VLOCAL); + t->k = VINDEXED; +} + +static int constfolding(OpCode op, ktap_expdesc *e1, ktap_expdesc *e2) +{ + ktap_number r; + + if (!isnumeral(e1) || !isnumeral(e2)) + return 0; + + if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) + return 0; /* do not attempt to divide by 0 */ + + if (op == OP_POW) + return 0; /* ktap current do not suppor pow arith */ + + r = ktapc_arith(op - OP_ADD + KTAP_OPADD, e1->u.nval, e2->u.nval); + e1->u.nval = r; + return 1; +} + +static void codearith(ktap_funcstate *fs, OpCode op, + ktap_expdesc *e1, ktap_expdesc *e2, int line) +{ + if (constfolding(op, e1, e2)) + return; + else { + int o2 = (op != OP_UNM && op != OP_LEN) ? codegen_exp2RK(fs, e2) : 0; + int o1 = codegen_exp2RK(fs, e1); + + if (o1 > o2) { + freeexp(fs, e1); + freeexp(fs, e2); + } else { + freeexp(fs, e2); + freeexp(fs, e1); + } + e1->u.info = codegen_codeABC(fs, op, 0, o1, o2); + e1->k = VRELOCABLE; + codegen_fixline(fs, line); + } +} + +static void codecomp(ktap_funcstate *fs, OpCode op, int cond, ktap_expdesc *e1, + ktap_expdesc *e2) +{ + int o1 = codegen_exp2RK(fs, e1); + int o2 = codegen_exp2RK(fs, e2); + + freeexp(fs, e2); + freeexp(fs, e1); + if (cond == 0 && op != OP_EQ) { + int temp; /* exchange args to replace by `<' or `<=' */ + temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ + cond = 1; + } + e1->u.info = condjump(fs, op, cond, o1, o2); + e1->k = VJMP; +} + +void codegen_prefix(ktap_funcstate *fs, UnOpr op, ktap_expdesc *e, int line) +{ + ktap_expdesc e2; + + e2.t = e2.f = NO_JUMP; + e2.k = VKNUM; + e2.u.nval = 0; + + switch (op) { + case OPR_MINUS: { + if (isnumeral(e)) /* minus constant? */ + e->u.nval = ktap_numunm(e->u.nval); /* fold it */ + else { + codegen_exp2anyreg(fs, e); + codearith(fs, OP_UNM, e, &e2, line); + } + break; + } + case OPR_NOT: + codenot(fs, e); + break; + case OPR_LEN: { + codegen_exp2anyreg(fs, e); /* cannot operate on constants */ + codearith(fs, OP_LEN, e, &e2, line); + break; + } + default: + ktap_assert(0); + } +} + +void codegen_infix(ktap_funcstate *fs, BinOpr op, ktap_expdesc *v) +{ + switch (op) { + case OPR_AND: { + codegen_goiftrue(fs, v); + break; + } + case OPR_OR: { + codegen_goiffalse(fs, v); + break; + } + case OPR_CONCAT: { + codegen_exp2nextreg(fs, v); /* operand must be on the `stack' */ + break; + } + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_MOD: case OPR_POW: { + if (!isnumeral(v)) codegen_exp2RK(fs, v); + break; + } + default: + codegen_exp2RK(fs, v); + break; + } +} + +void codegen_posfix(ktap_funcstate *fs, BinOpr op, ktap_expdesc *e1, ktap_expdesc *e2, int line) +{ + switch (op) { + case OPR_AND: { + ktap_assert(e1->t == NO_JUMP); /* list must be closed */ + codegen_dischargevars(fs, e2); + codegen_concat(fs, &e2->f, e1->f); + *e1 = *e2; + break; + } + case OPR_OR: { + ktap_assert(e1->f == NO_JUMP); /* list must be closed */ + codegen_dischargevars(fs, e2); + codegen_concat(fs, &e2->t, e1->t); + *e1 = *e2; + break; + } + case OPR_CONCAT: { + codegen_exp2val(fs, e2); + if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { + ktap_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1); + freeexp(fs, e1); + SETARG_B(getcode(fs, e2), e1->u.info); + e1->k = VRELOCABLE; e1->u.info = e2->u.info; + } else { + codegen_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ + codearith(fs, OP_CONCAT, e1, e2, line); + } + break; + } + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_MOD: case OPR_POW: { + codearith(fs, (OpCode)(op - OPR_ADD + OP_ADD), e1, e2, line); + break; + } + case OPR_EQ: case OPR_LT: case OPR_LE: { + codecomp(fs, (OpCode)(op - OPR_EQ + OP_EQ), 1, e1, e2); + break; + } + case OPR_NE: case OPR_GT: case OPR_GE: { + codecomp(fs, (OpCode)(op - OPR_NE + OP_EQ), 0, e1, e2); + break; + } + default: + ktap_assert(0); + } +} + +void codegen_fixline(ktap_funcstate *fs, int line) +{ + fs->f->lineinfo[fs->pc - 1] = line; +} + +void codegen_setlist(ktap_funcstate *fs, int base, int nelems, int tostore) +{ + int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; + int b = (tostore == KTAP_MULTRET) ? 0 : tostore; + + ktap_assert(tostore != 0); + if (c <= MAXARG_C) + codegen_codeABC(fs, OP_SETLIST, base, b, c); + else if (c <= MAXARG_Ax) { + codegen_codeABC(fs, OP_SETLIST, base, b, 0); + codeextraarg(fs, c); + } else + lex_syntaxerror(fs->ls, "constructor too long"); + fs->freereg = base + 1; /* free registers with list values */ +} + diff --git a/drivers/staging/ktap/userspace/dump.c b/drivers/staging/ktap/userspace/dump.c new file mode 100644 index 000000000000..088b08d0fa8e --- /dev/null +++ b/drivers/staging/ktap/userspace/dump.c @@ -0,0 +1,187 @@ +/* + * dump.c - save precompiled ktap chunks + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * Copyright (C) 1994-2013 Lua.org, PUC-Rio. + * - The part of code in this file is copied from lua initially. + * - lua's MIT license is compatible with GPL. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../include/ktap_types.h" +#include "../include/ktap_opcodes.h" +#include "ktapc.h" + + +typedef struct { + ktap_writer writer; + void *data; + int strip; + int status; +} DumpState; + +#define DumpMem(b, n, size, D) DumpBlock(b, (n)*(size), D) +#define DumpVar(x, D) DumpMem(&x, 1, sizeof(x), D) + +static void DumpBlock(const void *b, size_t size, DumpState *D) +{ + if (D->status == 0) + D->status = ((D->writer))(b, size, D->data); +} + +static void DumpChar(int y, DumpState *D) +{ + char x = (char)y; + DumpVar(x, D); +} + +static void DumpInt(int x, DumpState *D) +{ + DumpVar(x, D); +} + +static void DumpNumber(ktap_number x, DumpState *D) +{ + DumpVar(x,D); +} + +static void DumpVector(const void *b, int n, size_t size, DumpState *D) +{ + DumpInt(n, D); + DumpMem(b, n, size, D); +} + +static void DumpString(const ktap_string *s, DumpState *D) +{ + if (s == NULL) { + int size = 0; + DumpVar(size, D); + } else { + int size = s->tsv.len + 1; /* include trailing '\0' */ + DumpVar(size, D); + DumpBlock(getstr(s), size * sizeof(char), D); + } +} + +#define DumpCode(f, D) DumpVector(f->code, f->sizecode, sizeof(ktap_instruction), D) + +static void DumpFunction(const ktap_proto *f, DumpState *D); + +static void DumpConstants(const ktap_proto *f, DumpState *D) +{ + int i, n = f->sizek; + + DumpInt(n, D); + for (i = 0; i < n; i++) { + const ktap_value* o=&f->k[i]; + DumpChar(ttypenv(o), D); + switch (ttypenv(o)) { + case KTAP_TNIL: + break; + case KTAP_TBOOLEAN: + DumpChar(bvalue(o), D); + break; + case KTAP_TNUMBER: + DumpNumber(nvalue(o), D); + break; + case KTAP_TSTRING: + DumpString(rawtsvalue(o), D); + break; + default: + printf("ktap: DumpConstants with unknown vaule type %d\n", ttypenv(o)); + ktap_assert(0); + } + } + n = f->sizep; + DumpInt(n, D); + for (i = 0; i < n; i++) + DumpFunction(f->p[i], D); +} + +static void DumpUpvalues(const ktap_proto *f, DumpState *D) +{ + int i, n = f->sizeupvalues; + + DumpInt(n, D); + for (i = 0; i < n; i++) { + DumpChar(f->upvalues[i].instack, D); + DumpChar(f->upvalues[i].idx, D); + } +} + +static void DumpDebug(const ktap_proto *f, DumpState *D) +{ + int i,n; + + DumpString((D->strip) ? NULL : f->source, D); + n= (D->strip) ? 0 : f->sizelineinfo; + DumpVector(f->lineinfo, n, sizeof(int), D); + n = (D->strip) ? 0 : f->sizelocvars; + DumpInt(n, D); + + for (i = 0; i < n; i++) { + DumpString(f->locvars[i].varname, D); + DumpInt(f->locvars[i].startpc, D); + DumpInt(f->locvars[i].endpc, D); + } + n = (D->strip) ? 0 : f->sizeupvalues; + DumpInt(n, D); + for (i = 0; i < n; i++) + DumpString(f->upvalues[i].name, D); +} + +static void DumpFunction(const ktap_proto *f, DumpState *D) +{ + DumpInt(f->linedefined, D); + DumpInt(f->lastlinedefined, D); + DumpChar(f->numparams, D); + DumpChar(f->is_vararg, D); + DumpChar(f->maxstacksize, D); + DumpCode(f, D); + DumpConstants(f, D); + DumpUpvalues(f, D); + DumpDebug(f, D); +} + +static void DumpHeader(DumpState *D) +{ + u8 h[KTAPC_HEADERSIZE]; + + kp_header(h); + DumpBlock(h, KTAPC_HEADERSIZE, D); +} + +/* + * dump ktap function as precompiled chunk + */ +int ktapc_dump(const ktap_proto *f, ktap_writer w, void *data, int strip) +{ + DumpState D; + + D.writer = w; + D.data = data; + D.strip = strip; + D.status = 0; + DumpHeader(&D); + DumpFunction(f, &D); + return D.status; +} diff --git a/drivers/staging/ktap/userspace/eventdef.c b/drivers/staging/ktap/userspace/eventdef.c new file mode 100644 index 000000000000..76a68ac8aabc --- /dev/null +++ b/drivers/staging/ktap/userspace/eventdef.c @@ -0,0 +1,588 @@ +/* + * eventdef.c - ktap eventdef parser + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <dirent.h> +#include <fcntl.h> + +#include "../include/ktap_types.h" +#include "../include/ktap_opcodes.h" +#include "ktapc.h" + +static char tracing_events_path[] = "/sys/kernel/debug/tracing/events"; + +#define IDS_ARRAY_SIZE 4096 +static u8 *ids_array; + +#define set_id(id) \ + do { \ + ids_array[id/8] = ids_array[id/8] | (1 << (id%8)); \ + } while(0) + +#define clear_id(id) \ + do { \ + ids_array[id/8] = ids_array[id/8] & ~ (1 << (id%8)); \ + } while(0) + + +static int get_digit_len(int id) +{ + int len = -1; + + if (id < 10) + len = 1; + else if (id < 100) + len = 2; + else if (id < 1000) + len = 3; + else if (id < 10000) + len = 4; + else if (id < 100000) + len = 5; + + return len; +} + +static char *get_idstr(char *filter) +{ + char *idstr, *ptr; + int total_len = 0; + int filter_len; + int i; + + filter_len = filter ? strlen(filter) : 0; + + for (i = 0; i < IDS_ARRAY_SIZE*8; i++) { + if (ids_array[i/8] & (1 << (i%8))) + total_len += get_digit_len(i) + 1; + } + + if (!total_len) + return NULL; + + idstr = malloc(total_len + filter_len + 1); + if (!idstr) + return NULL; + + memset(idstr, 0, total_len + filter_len + 1); + ptr = idstr; + for (i = 0; i < IDS_ARRAY_SIZE*8; i++) { + if (ids_array[i/8] & (1 << (i%8))) { + char digits[32] = {0}; + int len; + + sprintf(digits, "%d ", i); + len = strlen(digits); + strncpy(ptr, digits, len); + ptr += len; + } + } + + if (filter) + memcpy(ptr, filter, strlen(filter)); + + return idstr; +} + +static int add_event(char *evtid_path) +{ + char id_buf[24]; + int id, fd; + + fd = open(evtid_path, O_RDONLY); + if (fd < 0) { + /* + * some tracepoint doesn't have id file, like ftrace, + * return success in here, and don't print error. + */ + verbose_printf("warning: cannot open file %s\n", evtid_path); + return 0; + } + + if (read(fd, id_buf, sizeof(id_buf)) < 0) { + fprintf(stderr, "read file error %s\n", evtid_path); + close(fd); + return -1; + } + + id = atoll(id_buf); + + if (id >= IDS_ARRAY_SIZE * 8) { + fprintf(stderr, "tracepoint id(%d) is bigger than %d\n", id, + IDS_ARRAY_SIZE * 8); + close(fd); + return -1; + } + + set_id(id); + + close(fd); + return 0; +} + +static int add_tracepoint(char *sys_name, char *evt_name) +{ + char evtid_path[PATH_MAX] = {0}; + + + snprintf(evtid_path, PATH_MAX, "%s/%s/%s/id", tracing_events_path, + sys_name, evt_name); + return add_event(evtid_path); +} + +static int add_tracepoint_multi_event(char *sys_name, char *evt_name) +{ + char evt_path[PATH_MAX]; + struct dirent *evt_ent; + DIR *evt_dir; + int ret = 0; + + snprintf(evt_path, PATH_MAX, "%s/%s", tracing_events_path, sys_name); + evt_dir = opendir(evt_path); + if (!evt_dir) { + perror("Can't open event dir"); + return -1; + } + + while (!ret && (evt_ent = readdir(evt_dir))) { + if (!strcmp(evt_ent->d_name, ".") + || !strcmp(evt_ent->d_name, "..") + || !strcmp(evt_ent->d_name, "enable") + || !strcmp(evt_ent->d_name, "filter")) + continue; + + if (!strglobmatch(evt_ent->d_name, evt_name)) + continue; + + ret = add_tracepoint(sys_name, evt_ent->d_name); + } + + closedir(evt_dir); + return ret; +} + +static int add_tracepoint_event(char *sys_name, char *evt_name) +{ + return strpbrk(evt_name, "*?") ? + add_tracepoint_multi_event(sys_name, evt_name) : + add_tracepoint(sys_name, evt_name); +} + +static int add_tracepoint_multi_sys(char *sys_name, char *evt_name) +{ + struct dirent *events_ent; + DIR *events_dir; + int ret = 0; + + events_dir = opendir(tracing_events_path); + if (!events_dir) { + perror("Can't open event dir"); + return -1; + } + + while (!ret && (events_ent = readdir(events_dir))) { + if (!strcmp(events_ent->d_name, ".") + || !strcmp(events_ent->d_name, "..") + || !strcmp(events_ent->d_name, "enable") + || !strcmp(events_ent->d_name, "header_event") + || !strcmp(events_ent->d_name, "header_page")) + continue; + + if (!strglobmatch(events_ent->d_name, sys_name)) + continue; + + ret = add_tracepoint_event(events_ent->d_name, + evt_name); + } + + closedir(events_dir); + return ret; +} + +static int parse_events_add_tracepoint(char *sys, char *event) +{ + if (strpbrk(sys, "*?")) + return add_tracepoint_multi_sys(sys, event); + else + return add_tracepoint_event(sys, event); +} + +enum { + KPROBE_EVENT, + UPROBE_EVENT, +}; + +struct probe_list { + struct probe_list *next; + int type; + int kp_seq; + char *probe_event; +}; + +static struct probe_list *probe_list_head; + +#define KPROBE_EVENTS_PATH "/sys/kernel/debug/tracing/kprobe_events" + +static int parse_events_add_kprobe(char *old_event) +{ + static int event_seq = 0; + struct probe_list *pl; + char probe_event[128] = {0}; + char event_id_path[128] = {0}; + char *event; + char *r; + int fd; + int ret; + + fd = open(KPROBE_EVENTS_PATH, O_WRONLY); + if (fd < 0) { + fprintf(stderr, "Cannot open %s\n", KPROBE_EVENTS_PATH); + return -1; + } + + event = strdup(old_event); + r = strstr(event, "%return"); + if (r) { + memset(r, ' ', 7); + snprintf(probe_event, 128, "r:kprobes/kp%d %s", + event_seq, event); + } else + snprintf(probe_event, 128, "p:kprobes/kp%d %s", + event_seq, event); + + free(event); + + verbose_printf("kprobe event %s\n", probe_event); + ret = write(fd, probe_event, strlen(probe_event)); + if (ret <= 0) { + fprintf(stderr, "Cannot write %s to %s\n", probe_event, + KPROBE_EVENTS_PATH); + close(fd); + return -1; + } + + close(fd); + + pl = malloc(sizeof(struct probe_list)); + if (!pl) + return -1; + + pl->type = KPROBE_EVENT; + pl->kp_seq = event_seq; + pl->next = probe_list_head; + probe_list_head = pl; + + sprintf(event_id_path, "/sys/kernel/debug/tracing/events/kprobes/kp%d/id", + event_seq); + ret = add_event(event_id_path); + if (ret < 0) + return -1; + + event_seq++; + return 0; +} + +#define UPROBE_EVENTS_PATH "/sys/kernel/debug/tracing/uprobe_events" + +static int parse_events_add_uprobe(char *old_event) +{ + static int event_seq = 0; + struct probe_list *pl; + char probe_event[128] = {0}; + char event_id_path[128] = {0}; + char *event; + char *r; + int fd; + int ret; + + fd = open(UPROBE_EVENTS_PATH, O_WRONLY); + if (fd < 0) { + fprintf(stderr, "Cannot open %s\n", UPROBE_EVENTS_PATH); + return -1; + } + + event = strdup(old_event); + r = strstr(event, "%return"); + if (r) { + memset(r, ' ', 7); + snprintf(probe_event, 128, "r:uprobes/kp%d %s", + event_seq, event); + } else + snprintf(probe_event, 128, "p:uprobes/kp%d %s", + event_seq, event); + + free(event); + + verbose_printf("uprobe event %s\n", probe_event); + ret = write(fd, probe_event, strlen(probe_event)); + if (ret <= 0) { + fprintf(stderr, "Cannot write %s to %s\n", probe_event, + UPROBE_EVENTS_PATH); + close(fd); + return -1; + } + + close(fd); + + pl = malloc(sizeof(struct probe_list)); + if (!pl) + return -1; + + pl->type = UPROBE_EVENT; + pl->kp_seq = event_seq; + pl->next = probe_list_head; + probe_list_head = pl; + + sprintf(event_id_path, "/sys/kernel/debug/tracing/events/uprobes/kp%d/id", + event_seq); + ret = add_event(event_id_path); + if (ret < 0) + return -1; + + event_seq++; + return 0; +} + +static int parse_events_add_probe(char *old_event) +{ + char *separator; + + separator = strchr(old_event, ':'); + if (!separator || (separator == old_event)) + return parse_events_add_kprobe(old_event); + else + return parse_events_add_uprobe(old_event); +} + +static int parse_events_add_stapsdt(char *old_event) +{ + printf("Currently ktap don't support stapsdt, please waiting\n"); + + return -1; +} + +static void strim(char *s) +{ + size_t size; + char *end; + + size = strlen(s); + if (!size) + return; + + end = s + size -1; + while (end >= s && isspace(*end)) + end--; + + *(end + 1) = '\0'; +} + +static int get_sys_event_filter_str(char *start, + char **sys, char **event, char **filter) +{ + char *separator, *separator2, *ptr, *end; + + while (*start == ' ') + start++; + + /* find sys */ + separator = strchr(start, ':'); + if (!separator || (separator == start)) { + return -1; + } + + ptr = malloc(separator - start + 1); + if (!ptr) + return -1; + + strncpy(ptr, start, separator - start); + ptr[separator - start] = '\0'; + + strim(ptr); + *sys = ptr; + + if (!strcmp(*sys, "probe") && (*(separator + 1) == '/')) { + /* it's uprobe event */ + separator2 = strchr(separator + 1, ':'); + if (!separator2) + return -1; + } else + separator2 = separator; + + /* find filter */ + end = start + strlen(start); + while (*--end == ' ') { + } + + if (*end == '/') { + char *filter_start; + + filter_start = strchr(separator2, '/'); + if (filter_start == end) + return -1; + + ptr = malloc(end - filter_start + 2); + if (!ptr) + return -1; + + memcpy(ptr, filter_start, end - filter_start + 1); + ptr[end - filter_start + 1] = '\0'; + + *filter = ptr; + + end = filter_start; + } else { + *filter = NULL; + end++; + } + + /* find event */ + ptr = malloc(end - separator); + if (!ptr) + return -1; + + memcpy(ptr, separator + 1, end - separator - 1); + ptr[end - separator - 1] = '\0'; + + strim(ptr); + *event = ptr; + + return 0; +} + +static char *get_next_eventdef(char *str) +{ + char *separator; + + separator = strchr(str, ','); + if (!separator) + return str + strlen(str); + + *separator = '\0'; + return separator + 1; +} + +ktap_string *ktapc_parse_eventdef(ktap_string *eventdef) +{ + const char *def_str = getstr(eventdef); + char *str = strdup(def_str); + char *sys, *event, *filter, *idstr, *g_idstr, *next; + ktap_string *ts; + int ret; + + if (!ids_array) { + ids_array = malloc(IDS_ARRAY_SIZE); + if (!ids_array) + return NULL; + } + + g_idstr = malloc(4096); + if (!g_idstr) + return NULL; + + memset(g_idstr, 0, 4096); + + parse_next_eventdef: + memset(ids_array, 0, IDS_ARRAY_SIZE); + + next = get_next_eventdef(str); + + if (get_sys_event_filter_str(str, &sys, &event, &filter)) + goto error; + + verbose_printf("parse_eventdef: sys[%s], event[%s], filter[%s]\n", + sys, event, filter); + + if (!strcmp(sys, "probe")) + ret = parse_events_add_probe(event); + else if (!strcmp(sys, "stapsdt")) + ret = parse_events_add_stapsdt(event); + else + ret = parse_events_add_tracepoint(sys, event); + + if (ret) + goto error; + + /* don't trace ftrace:function when all tracepoints enabled */ + if (!strcmp(sys, "*")) + clear_id(1); + + idstr = get_idstr(filter); + if (!idstr) + goto error; + + str = next; + + g_idstr = strcat(g_idstr, idstr); + g_idstr = strcat(g_idstr, ","); + + if (*next != '\0') + goto parse_next_eventdef; + + ts = ktapc_ts_new(g_idstr); + free(g_idstr); + + return ts; + error: + cleanup_event_resources(); + return NULL; +} + +void cleanup_event_resources(void) +{ + struct probe_list *pl; + const char *path; + char probe_event[32] = {0}; + int fd, ret; + + for (pl = probe_list_head; pl; pl = pl->next) { + if (pl->type == KPROBE_EVENT) { + path = KPROBE_EVENTS_PATH; + snprintf(probe_event, 32, "-:kprobes/kp%d", pl->kp_seq); + } else if (pl->type == UPROBE_EVENT) { + path = UPROBE_EVENTS_PATH; + snprintf(probe_event, 32, "-:uprobes/kp%d", pl->kp_seq); + } else { + fprintf(stderr, "Cannot cleanup event type %d\n", pl->type); + continue; + } + + fd = open(path, O_WRONLY); + if (fd < 0) { + fprintf(stderr, "Cannot open %s\n", UPROBE_EVENTS_PATH); + continue; + } + + ret = write(fd, probe_event, strlen(probe_event)); + if (ret <= 0) { + fprintf(stderr, "Cannot write %s to %s\n", probe_event, + path); + close(fd); + continue; + } + + close(fd); + } +} + diff --git a/drivers/staging/ktap/userspace/ktapc.h b/drivers/staging/ktap/userspace/ktapc.h new file mode 100644 index 000000000000..879cd29d8c94 --- /dev/null +++ b/drivers/staging/ktap/userspace/ktapc.h @@ -0,0 +1,376 @@ +/* + * ktapc.h + * only can be included by userspace compiler + */ + +#include <ctype.h> + +typedef int bool; +#define false 0 +#define true 1 + +#define MAX_INT ((int)(~0U>>1)) +#define UCHAR_MAX 255 + +#define MAX_SIZET ((size_t)(~(size_t)0)-2) + +#define KTAP_ERRSYNTAX 3 + +/* + * KTAP_IDSIZE gives the maximum size for the description of the source + * of a function in debug information. + * CHANGE it if you want a different size. + */ +#define KTAP_IDSIZE 60 + + +#define FIRST_RESERVED 257 + +/* + * maximum depth for nested C calls and syntactical nested non-terminals + * in a program. (Value must fit in an unsigned short int.) + */ +#define KTAP_MAXCCALLS 200 + +#define KTAP_MULTRET (-1) + + +#define SHRT_MAX UCHAR_MAX + +#define MAXUPVAL UCHAR_MAX + + +/* maximum stack for a ktap function */ +#define MAXSTACK 250 + +#define islalpha(c) (isalpha(c) || (c) == '_') +#define islalnum(c) (isalnum(c) || (c) == '_') + +#define isreserved(s) ((s)->tsv.tt == KTAP_TSHRSTR && (s)->tsv.extra > 0) + +#define ktap_numeq(a,b) ((a)==(b)) +#define ktap_numisnan(L,a) (!ktap_numeq((a), (a))) + +#define ktap_numunm(a) (-(a)) + +/* + * ** Comparison and arithmetic functions + * */ + +#define KTAP_OPADD 0 /* ORDER TM */ +#define KTAP_OPSUB 1 +#define KTAP_OPMUL 2 +#define KTAP_OPDIV 3 +#define KTAP_OPMOD 4 +#define KTAP_OPPOW 5 +#define KTAP_OPUNM 6 + +#define KTAP_OPEQ 0 +#define KTAP_OPLT 1 +#define KTAP_OPLE 2 + + +/* + * WARNING: if you change the order of this enumeration, + * grep "ORDER RESERVED" + */ +enum RESERVED { + /* terminal symbols denoted by reserved words */ + TK_TRACE = FIRST_RESERVED, TK_TRACE_END, + TK_ARGEVENT, TK_ARGNAME, + TK_ARG1, TK_ARG2, TK_ARG3, TK_ARG4, TK_ARG5, TK_ARG6, TK_ARG7, TK_ARG8, + TK_ARG9, TK_PROFILE, TK_TICK, + TK_AND, TK_BREAK, + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, + TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_INCR, TK_DBCOLON, + TK_EOS, TK_NUMBER, TK_NAME, TK_STRING +}; + +/* number of reserved words */ +#define NUM_RESERVED ((int)(TK_WHILE-FIRST_RESERVED + 1)) + +#define EOZ (0) /* end of stream */ + +typedef union { + ktap_number r; + ktap_string *ts; +} ktap_seminfo; /* semantics information */ + + +typedef struct ktap_token { + int token; + ktap_seminfo seminfo; +} ktap_token; + +typedef struct ktap_mbuffer { + char *buffer; + size_t n; + size_t buffsize; +} ktap_mbuffer; + +#define mbuff_init(buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) +#define mbuff(buff) ((buff)->buffer) +#define mbuff_reset(buff) ((buff)->n = 0, memset((buff)->buffer, 0, (buff)->buffsize)) +#define mbuff_len(buff) ((buff)->n) +#define mbuff_size(buff) ((buff)->buffsize) + +#define mbuff_resize(buff, size) \ + (ktapc_realloc((buff)->buffer, (buff)->buffsize, size, char), \ + (buff)->buffsize = size) + +#define mbuff_free(buff) mbuff_resize(buff, 0) + + +/* + * state of the lexer plus state of the parser when shared by all + * functions + */ +typedef struct ktap_lexstate { + char *ptr; /* source file reading position */ + int current; /* current character (charint) */ + int linenumber; /* input line counter */ + int lastline; /* line of last token `consumed' */ + ktap_token t; /* current token */ + ktap_token lookahead; /* look ahead token */ + struct ktap_funcstate *fs; /* current function (parser) */ + ktap_mbuffer *buff; /* buffer for tokens */ + struct ktap_dyndata *dyd; /* dynamic structures used by the parser */ + ktap_string *source; /* current source name */ + ktap_string *envn; /* environment variable name */ + char decpoint; /* locale decimal point */ + int nCcalls; +} ktap_lexstate; + + +/* + * Expression descriptor + */ +typedef enum { + VVOID, /* no value */ + VNIL, + VTRUE, + VFALSE, + VK, /* info = index of constant in `k' */ + VKNUM, /* nval = numerical value */ + VNONRELOC, /* info = result register */ + VLOCAL, /* info = local register */ + VUPVAL, /* info = index of upvalue in 'upvalues' */ + VINDEXED, /* t = table register/upvalue; idx = index R/K */ + VJMP, /* info = instruction pc */ + VRELOCABLE, /* info = instruction pc */ + VCALL, /* info = instruction pc */ + VVARARG, /* info = instruction pc */ + VEVENT, + VEVENTNAME, + VEVENTARG, +} expkind; + + +#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) +#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) + +typedef struct ktap_expdesc { + expkind k; + union { + struct { /* for indexed variables (VINDEXED) */ + short idx; /* index (R/K) */ + u8 t; /* table (register or upvalue) */ + u8 vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ + } ind; + int info; /* for generic use */ + ktap_number nval; /* for VKNUM */ + } u; + int t; /* patch list of `exit when true' */ + int f; /* patch list of `exit when false' */ +} ktap_expdesc; + + +typedef struct ktap_vardesc { + short idx; /* variable index in stack */ +} ktap_vardesc; + + +/* description of pending goto statements and label statements */ +typedef struct ktap_labeldesc { + ktap_string *name; /* label identifier */ + int pc; /* position in code */ + int line; /* line where it appeared */ + u8 nactvar; /* local level where it appears in current block */ +} ktap_labeldesc; + + +/* list of labels or gotos */ +typedef struct ktap_labellist { + ktap_labeldesc *arr; /* array */ + int n; /* number of entries in use */ + int size; /* array size */ +} ktap_labellist; + + +/* dynamic structures used by the parser */ +typedef struct ktap_dyndata { + struct { /* list of active local variables */ + ktap_vardesc *arr; + int n; + int size; + } actvar; + ktap_labellist gt; /* list of pending gotos */ + ktap_labellist label; /* list of active labels */ +} ktap_dyndata; + + +/* control of blocks */ +struct ktap_blockcnt; /* defined in lparser.c */ + + +/* state needed to generate code for a given function */ +typedef struct ktap_funcstate { + ktap_proto *f; /* current function header */ + ktap_table *h; /* table to find (and reuse) elements in `k' */ + struct ktap_funcstate *prev; /* enclosing function */ + struct ktap_lexstate *ls; /* lexical state */ + struct ktap_blockcnt *bl; /* chain of current blocks */ + int pc; /* next position to code (equivalent to `ncode') */ + int lasttarget; /* 'label' of last 'jump label' */ + int jpc; /* list of pending jumps to `pc' */ + int nk; /* number of elements in `k' */ + int np; /* number of elements in `p' */ + int firstlocal; /* index of first local var (in ktap_dyndata array) */ + short nlocvars; /* number of elements in 'f->locvars' */ + u8 nactvar; /* number of active local variables */ + u8 nups; /* number of upvalues */ + u8 freereg; /* first free register */ +} ktap_funcstate; + + +/* + * Marks the end of a patch list. It is an invalid value both as an absolute + * address, and as a list link (would link an element to itself). + */ +#define NO_JUMP (-1) + + +/* + * grep "ORDER OPR" if you change these enums (ORDER OP) + */ +typedef enum BinOpr { + OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, + OPR_CONCAT, + OPR_EQ, OPR_LT, OPR_LE, + OPR_NE, OPR_GT, OPR_GE, + OPR_AND, OPR_OR, + OPR_NOBINOPR +} BinOpr; + + +typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; + + +#define getcode(fs,e) ((fs)->f->code[(e)->u.info]) + +#define codegen_codeAsBx(fs,o,A,sBx) codegen_codeABx(fs,o,A,(sBx)+MAXARG_sBx) + +#define codegen_setmultret(fs,e) codegen_setreturns(fs, e, KTAP_MULTRET) + +#define codegen_jumpto(fs,t) codegen_patchlist(fs, codegen_jump(fs), t) + + +#define ktapc_realloc(v, osize, nsize, t) \ + ((v) = (t *)ktapc_reallocv(v, osize * sizeof(t), nsize * sizeof(t))) + +#define ktapc_reallocvector(v,oldn,n,t) ktapc_realloc(v,oldn,n,t) + + +#define ktapc_growvector(v,nelems,size,t,limit,e) \ + if ((nelems)+1 > (size)) \ + ((v)=(t *)ktapc_growaux(v,&(size),sizeof(t),limit,e)) + + +void lex_init(); +ktap_string *lex_newstring(ktap_lexstate *ls, const char *str, size_t l); +const char *lex_token2str(ktap_lexstate *ls, int token); +void lex_syntaxerror(ktap_lexstate *ls, const char *msg); +void lex_setinput(ktap_lexstate *ls, char *ptr, ktap_string *source, int firstchar); +void lex_next(ktap_lexstate *ls); +int lex_lookahead(ktap_lexstate *ls); +void lex_read_string_until(ktap_lexstate *ls, int c); +ktap_closure *ktapc_parser(char *pos, const char *name); +ktap_string *ktapc_ts_new(const char *str); +int ktapc_ts_eqstr(ktap_string *a, ktap_string *b); +ktap_string *ktapc_ts_newlstr(const char *str, size_t l); +ktap_proto *ktapc_newproto(); +ktap_table *ktapc_table_new(); +const ktap_value *ktapc_table_get(ktap_table *t, const ktap_value *key); +void ktapc_table_setvalue(ktap_table *t, const ktap_value *key, ktap_value *val); +ktap_closure *ktapc_newlclosure(int n); +char *ktapc_sprintf(const char *fmt, ...); + +void *ktapc_reallocv(void *block, size_t osize, size_t nsize); +void *ktapc_growaux(void *block, int *size, size_t size_elems, int limit, + const char *what); + +void ktapio_exit(void); +int ktapio_create(const char *output_filename); + +ktap_string *ktapc_parse_eventdef(ktap_string *eventdef); +void cleanup_event_resources(void); + +extern int verbose; +#define verbose_printf(...) \ + if (verbose) \ + printf("[verbose] " __VA_ARGS__); + +#define ktapc_equalobj(t1, t2) kp_equalobjv(NULL, t1, t2) + + +#include "../include/ktap_opcodes.h" + +int codegen_stringK(ktap_funcstate *fs, ktap_string *s); +void codegen_indexed(ktap_funcstate *fs, ktap_expdesc *t, ktap_expdesc *k); +void codegen_setreturns(ktap_funcstate *fs, ktap_expdesc *e, int nresults); +void codegen_reserveregs(ktap_funcstate *fs, int n); +void codegen_exp2nextreg(ktap_funcstate *fs, ktap_expdesc *e); +void codegen_nil(ktap_funcstate *fs, int from, int n); +void codegen_patchlist(ktap_funcstate *fs, int list, int target); +void codegen_patchclose(ktap_funcstate *fs, int list, int level); +int codegen_jump(ktap_funcstate *fs); +void codegen_patchtohere(ktap_funcstate *fs, int list); +int codegen_codeABx(ktap_funcstate *fs, OpCode o, int a, unsigned int bc); +void codegen_ret(ktap_funcstate *fs, int first, int nret); +void codegen_exp2anyregup(ktap_funcstate *fs, ktap_expdesc *e); +void codegen_exp2val(ktap_funcstate *fs, ktap_expdesc *e); +int codegen_exp2RK(ktap_funcstate *fs, ktap_expdesc *e); +int codegen_codeABC(ktap_funcstate *fs, OpCode o, int a, int b, int c); +void codegen_setlist(ktap_funcstate *fs, int base, int nelems, int tostore); +void codegen_fixline (ktap_funcstate *fs, int line); +void codegen_dischargevars(ktap_funcstate *fs, ktap_expdesc *e); +void codegen_self(ktap_funcstate *fs, ktap_expdesc *e, ktap_expdesc *key); +void codegen_prefix(ktap_funcstate *fs, UnOpr op, ktap_expdesc *e, int line); +void codegen_infix(ktap_funcstate *fs, BinOpr op, ktap_expdesc *v); +void codegen_posfix(ktap_funcstate *fs, BinOpr op, ktap_expdesc *e1, ktap_expdesc *e2, int line); +void codegen_setoneret(ktap_funcstate *fs, ktap_expdesc *e); +void codegen_storevar(ktap_funcstate *fs, ktap_expdesc *var, ktap_expdesc *ex); +void codegen_storeincr(ktap_funcstate *fs, ktap_expdesc *var, ktap_expdesc *ex); +void codegen_goiftrue(ktap_funcstate *fs, ktap_expdesc *e); +int codegen_getlabel(ktap_funcstate *fs); +int codegen_codek(ktap_funcstate *fs, int reg, int k); +int codegen_numberK(ktap_funcstate *fs, ktap_number r); +void codegen_checkstack(ktap_funcstate *fs, int n); +void codegen_goiffalse(ktap_funcstate *fs, ktap_expdesc *e); +void codegen_concat(ktap_funcstate *fs, int *l1, int l2); +int codegen_exp2anyreg(ktap_funcstate *fs, ktap_expdesc *e); + +typedef int (*ktap_writer)(const void* p, size_t sz, void* ud); +int ktapc_dump(const ktap_proto *f, ktap_writer w, void *data, int strip); + +void ktapc_chunkid(char *out, const char *source, size_t bufflen); +int ktapc_str2d(const char *s, size_t len, ktap_number *result); +int ktapc_hexavalue(int c); +ktap_number ktapc_arith(int op, ktap_number v1, ktap_number v2); +int ktapc_int2fb(unsigned int x); + +bool strglobmatch(const char *str, const char *pat); + diff --git a/drivers/staging/ktap/userspace/ktapio.c b/drivers/staging/ktap/userspace/ktapio.c new file mode 100644 index 000000000000..f9bcab461f2a --- /dev/null +++ b/drivers/staging/ktap/userspace/ktapio.c @@ -0,0 +1,108 @@ +/* + * ktapio.c - ring buffer transport in userspace + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/poll.h> +#include <sys/signal.h> +#include <fcntl.h> +#include <pthread.h> + +#define MAX_BUFLEN 131072 +#define PATH_MAX 128 + +#define handle_error(str) do { perror(str); exit(-1); } while(0) + +extern pid_t ktap_pid; + +void sigfunc(int signo) +{ + /* should not not reach here */ +} + +static void block_sigint() +{ + sigset_t mask; + + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + + pthread_sigmask(SIG_BLOCK, &mask, NULL); +} + +static void *reader_thread(void *data) +{ + char buf[MAX_BUFLEN]; + char filename[PATH_MAX]; + const char *output = data; + int failed = 0, fd, out_fd, len; + + block_sigint(); + + if (output) { + out_fd = open(output, O_CREAT | O_WRONLY | O_TRUNC, + S_IRUSR|S_IWUSR); + if (out_fd < 0) { + fprintf(stderr, "Cannot open output file %s\n", output); + return NULL; + } + } else + out_fd = 2; + + sprintf(filename, "/sys/kernel/debug/ktap/trace_pipe_%d", ktap_pid); + + open_again: + fd = open(filename, O_RDONLY); + if (fd < 0) { + usleep(10000); + + if (failed++ == 10) { + fprintf(stderr, "Cannot open file %s\n", filename); + return NULL; + } + goto open_again; + } + + while ((len = read(fd, buf, sizeof(buf))) > 0) + write(out_fd, buf, len); + + close(fd); + close(out_fd); + + return NULL; +} + +int ktapio_create(const char *output) +{ + pthread_t reader; + + signal(SIGINT, sigfunc); + + if (pthread_create(&reader, NULL, reader_thread, (void *)output) < 0) + handle_error("pthread_create reader_thread failed\n"); + + return 0; +} + diff --git a/drivers/staging/ktap/userspace/lex.c b/drivers/staging/ktap/userspace/lex.c new file mode 100644 index 000000000000..484dd7fdafc3 --- /dev/null +++ b/drivers/staging/ktap/userspace/lex.c @@ -0,0 +1,622 @@ +/* + * lex.c - ktap lexical analyzer + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * Copyright (C) 1994-2013 Lua.org, PUC-Rio. + * - The part of code in this file is copied from lua initially. + * - lua's MIT license is compatible with GPL. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <locale.h> +#include "../include/ktap_types.h" +#include "ktapc.h" + +#define next(ls) (ls->current = *ls->ptr++) + +#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') + +#define KTAP_MINBUFFER 32 + +/* ORDER RESERVED */ +static const char *const ktap_tokens [] = { + "trace", "trace_end", "argevent", "argname", + "arg1", "arg2", "arg3", "arg4", "arg5", "arg6", "arg7", "arg9", "arg9", + "profile", "tick", + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "goto", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "..", "...", "==", ">=", "<=", "!=", "+=", "::", "<eof>", + "<number>", "<name>", "<string>" +}; + +#define save_and_next(ls) (save(ls, ls->current), next(ls)) + +static void lexerror(ktap_lexstate *ls, const char *msg, int token); + +static void save(ktap_lexstate *ls, int c) +{ + ktap_mbuffer *b = ls->buff; + if (mbuff_len(b) + 1 > mbuff_size(b)) { + size_t newsize; + if (mbuff_size(b) >= MAX_SIZET / 2) + lexerror(ls, "lexical element too long", 0); + newsize = mbuff_size(b) * 2; + mbuff_resize(b, newsize); + } + b->buffer[mbuff_len(b)++] = (char)c; +} + +void lex_init() +{ + int i; + for (i = 0; i < NUM_RESERVED; i++) { + ktap_string *ts = ktapc_ts_new(ktap_tokens[i]); + ts->tsv.extra = (u8)(i+1); /* reserved word */ + } +} + +const char *lex_token2str(ktap_lexstate *ls, int token) +{ + if (token < FIRST_RESERVED) { + ktap_assert(token == (unsigned char)token); + return (isprint(token)) ? ktapc_sprintf(KTAP_QL("%c"), token) : + ktapc_sprintf("char(%d)", token); + } else { + const char *s = ktap_tokens[token - FIRST_RESERVED]; + if (token < TK_EOS) + return ktapc_sprintf(KTAP_QS, s); + else + return s; + } +} + +static const char *txtToken(ktap_lexstate *ls, int token) +{ + switch (token) { + case TK_NAME: + case TK_STRING: + case TK_NUMBER: + save(ls, '\0'); + return ktapc_sprintf(KTAP_QS, mbuff(ls->buff)); + default: + return lex_token2str(ls, token); + } +} + +static void lexerror(ktap_lexstate *ls, const char *msg, int token) +{ + char buff[KTAP_IDSIZE]; + char *newmsg; + + ktapc_chunkid(buff, getstr(ls->source), KTAP_IDSIZE); + newmsg = ktapc_sprintf("%s:%d: %s", buff, ls->linenumber, msg); + if (token) + newmsg = ktapc_sprintf("%s near %s", newmsg, txtToken(ls, token)); + printf("lexerror: %s\n", newmsg); + exit(EXIT_FAILURE); +} + +void lex_syntaxerror(ktap_lexstate *ls, const char *msg) +{ + lexerror(ls, msg, ls->t.token); +} + +/* + * creates a new string and anchors it in function's table so that + * it will not be collected until the end of the function's compilation + * (by that time it should be anchored in function's prototype) + */ +ktap_string *lex_newstring(ktap_lexstate *ls, const char *str, size_t l) +{ + const ktap_value *o; /* entry for `str' */ + ktap_value val; /* entry for `str' */ + ktap_value tsv; + ktap_string *ts = ktapc_ts_newlstr(str, l); /* create new string */ + setsvalue(&tsv, ts); + o = ktapc_table_get(ls->fs->h, &tsv); + if (ttisnil(o)) { /* not in use yet? (see 'addK') */ + /* boolean value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setbvalue(&val, 1); /* t[string] = true */ + ktapc_table_setvalue(ls->fs->h, &tsv, &val); + } + return ts; +} + +/* + * increment line number and skips newline sequence (any of + * \n, \r, \n\r, or \r\n) + */ +static void inclinenumber(ktap_lexstate *ls) +{ + int old = ls->current; + ktap_assert(currIsNewline(ls)); + next(ls); /* skip `\n' or `\r' */ + if (currIsNewline(ls) && ls->current != old) + next(ls); /* skip `\n\r' or `\r\n' */ + if (++ls->linenumber >= MAX_INT) + lex_syntaxerror(ls, "chunk has too many lines"); +} + +void lex_setinput(ktap_lexstate *ls, char *ptr, ktap_string *source, int firstchar) +{ + ls->decpoint = '.'; + ls->current = firstchar; + ls->lookahead.token = TK_EOS; /* no look-ahead token */ + ls->ptr = ptr; + ls->fs = NULL; + ls->linenumber = 1; + ls->lastline = 1; + ls->source = source; + ls->envn = ktapc_ts_new(KTAP_ENV); /* create env name */ + mbuff_resize(ls->buff, KTAP_MINBUFFER); /* initialize buffer */ +} + +/* + * ======================================================= + * LEXICAL ANALYZER + * ======================================================= + */ +static int check_next(ktap_lexstate *ls, const char *set) +{ + if (ls->current == '\0' || !strchr(set, ls->current)) + return 0; + save_and_next(ls); + return 1; +} + +/* + * change all characters 'from' in buffer to 'to' + */ +static void buffreplace(ktap_lexstate *ls, char from, char to) +{ + size_t n = mbuff_len(ls->buff); + char *p = mbuff(ls->buff); + while (n--) + if (p[n] == from) p[n] = to; +} + +#if !defined(getlocaledecpoint) +#define getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + +#define mbuff2d(b,e) ktapc_str2d(mbuff(b), mbuff_len(b) - 1, e) + +/* + * in case of format error, try to change decimal point separator to + * the one defined in the current locale and check again + */ +static void trydecpoint(ktap_lexstate *ls, ktap_seminfo *seminfo) +{ + char old = ls->decpoint; + ls->decpoint = getlocaledecpoint(); + buffreplace(ls, old, ls->decpoint); /* try new decimal separator */ + if (!mbuff2d(ls->buff, &seminfo->r)) { + /* format error with correct decimal point: no more options */ + buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ + lexerror(ls, "malformed number", TK_NUMBER); + } +} + +/* + * this function is quite liberal in what it accepts, as 'ktapc_str2d' + * will reject ill-formed numerals. + */ +static void read_numeral(ktap_lexstate *ls, ktap_seminfo *seminfo) +{ + const char *expo = "Ee"; + int first = ls->current; + + ktap_assert(isdigit(ls->current)); + save_and_next(ls); + if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */ + expo = "Pp"; + for (;;) { + if (check_next(ls, expo)) /* exponent part? */ + check_next(ls, "+-"); /* optional exponent sign */ + if (isxdigit(ls->current) || ls->current == '.') + save_and_next(ls); + else + break; + } + save(ls, '\0'); + buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ + if (!mbuff2d(ls->buff, &seminfo->r)) /* format error? */ + trydecpoint(ls, seminfo); /* try to update decimal point separator */ +} + +/* + * skip a sequence '[=*[' or ']=*]' and return its number of '='s or + * -1 if sequence is malformed + */ +static int skip_sep(ktap_lexstate *ls) +{ + int count = 0; + int s = ls->current; + + ktap_assert(s == '[' || s == ']'); + save_and_next(ls); + while (ls->current == '=') { + save_and_next(ls); + count++; + } + return (ls->current == s) ? count : (-count) - 1; +} + +static void read_long_string(ktap_lexstate *ls, ktap_seminfo *seminfo, int sep) +{ + save_and_next(ls); /* skip 2nd `[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) { + switch (ls->current) { + case EOZ: + lexerror(ls, (seminfo) ? "unfinished long string" : + "unfinished long comment", TK_EOS); + break; /* to avoid warnings */ + case ']': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `]' */ + goto endloop; + } + break; + } + case '\n': + case '\r': { + save(ls, '\n'); + inclinenumber(ls); + /* avoid wasting space */ + if (!seminfo) + mbuff_reset(ls->buff); + break; + } + default: { + if (seminfo) + save_and_next(ls); + else + next(ls); + } + } + } + + endloop: + if (seminfo) + seminfo->ts = lex_newstring(ls, mbuff(ls->buff) + (2 + sep), + mbuff_len(ls->buff) - 2*(2 + sep)); +} + +static void escerror(ktap_lexstate *ls, int *c, int n, const char *msg) +{ + int i; + mbuff_reset(ls->buff); /* prepare error message */ + save(ls, '\\'); + for (i = 0; i < n && c[i] != EOZ; i++) + save(ls, c[i]); + lexerror(ls, msg, TK_STRING); +} + +static int readhexaesc(ktap_lexstate *ls) +{ + int c[3], i; /* keep input for error message */ + int r = 0; /* result accumulator */ + c[0] = 'x'; /* for error message */ + for (i = 1; i < 3; i++) { /* read two hexa digits */ + c[i] = next(ls); + if (!isxdigit(c[i])) + escerror(ls, c, i + 1, "hexadecimal digit expected"); + r = (r << 4) + ktapc_hexavalue(c[i]); + } + return r; +} + +static int readdecesc(ktap_lexstate *ls) +{ + int c[3], i; + int r = 0; /* result accumulator */ + for (i = 0; i < 3 && isdigit(ls->current); i++) { /* read up to 3 digits */ + c[i] = ls->current; + r = 10*r + c[i] - '0'; + next(ls); + } + if (r > UCHAR_MAX) + escerror(ls, c, i, "decimal escape too large"); + return r; +} + +static void read_string(ktap_lexstate *ls, int del, ktap_seminfo *seminfo) +{ + save_and_next(ls); /* keep delimiter (for error messages) */ + while (ls->current != del) { + switch (ls->current) { + case EOZ: + lexerror(ls, "unfinished string", TK_EOS); + break; /* to avoid warnings */ + case '\n': + case '\r': + lexerror(ls, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': { /* escape sequences */ + int c; /* final character to be saved */ + next(ls); /* do not save the `\' */ + switch (ls->current) { + case 'a': c = '\a'; goto read_save; + case 'b': c = '\b'; goto read_save; + case 'f': c = '\f'; goto read_save; + case 'n': c = '\n'; goto read_save; + case 'r': c = '\r'; goto read_save; + case 't': c = '\t'; goto read_save; + case 'v': c = '\v'; goto read_save; + case 'x': c = readhexaesc(ls); goto read_save; + case '\n': case '\r': + inclinenumber(ls); c = '\n'; goto only_save; + case '\\': case '\"': case '\'': + c = ls->current; goto read_save; + case EOZ: goto no_save; /* will raise an error next loop */ + case 'z': { /* zap following span of spaces */ + next(ls); /* skip the 'z' */ + while (isspace(ls->current)) { + if (currIsNewline(ls)) + inclinenumber(ls); + else + next(ls); + } + goto no_save; + } + default: { + if (!isdigit(ls->current)) + escerror(ls, &ls->current, 1, "invalid escape sequence"); + /* digital escape \ddd */ + c = readdecesc(ls); + goto only_save; + } + } + read_save: + next(ls); /* read next character */ + only_save: + save(ls, c); /* save 'c' */ + no_save: + break; + } + default: + save_and_next(ls); + } + } + save_and_next(ls); /* skip delimiter */ + seminfo->ts = lex_newstring(ls, mbuff(ls->buff) + 1, mbuff_len(ls->buff) - 2); +} + +static int llex(ktap_lexstate *ls, ktap_seminfo *seminfo) +{ + mbuff_reset(ls->buff); + + for (;;) { + switch (ls->current) { + case '\n': case '\r': { /* line breaks */ + inclinenumber(ls); + break; + } + case ' ': case '\f': case '\t': case '\v': { /* spaces */ + next(ls); + break; + } + case '#': { + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); /* skip until end of line (or end of file) */ + break; + } + #if 0 + case '-': { /* '-' or '--' (comment) */ + next(ls); + if (ls->current != '-') + return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') { /* long comment? */ + int sep = skip_sep(ls); + mbuff_reset(ls->buff); /* `skip_sep' may dirty the buffer */ + if (sep >= 0) { + read_long_string(ls, NULL, sep); /* skip long comment */ + mbuff_reset(ls->buff); /* previous call may dirty the buff. */ + break; + } + } + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); /* skip until end of line (or end of file) */ + break; + } + #endif + case '[': { /* long string or simply '[' */ + int sep = skip_sep(ls); + if (sep >= 0) { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } + else if (sep == -1) + return '['; + else + lexerror(ls, "invalid long string delimiter", TK_STRING); + } + case '+': { + next(ls); + if (ls->current != '=') + return '+'; + else { + next(ls); + return TK_INCR; + } + } + case '=': { + next(ls); + if (ls->current != '=') + return '='; + else { + next(ls); + return TK_EQ; + } + } + case '<': { + next(ls); + if (ls->current != '=') + return '<'; + else { + next(ls); + return TK_LE; + } + } + case '>': { + next(ls); + if (ls->current != '=') + return '>'; + else { + next(ls); + return TK_GE; + } + } + case '!': { + next(ls); + if (ls->current != '=') + return TK_NOT; + else { + next(ls); + return TK_NE; + } + } + case ':': { + next(ls); + if (ls->current != ':') + return ':'; + else { + next(ls); + return TK_DBCOLON; + } + } + case '"': case '\'': { /* short literal strings */ + read_string(ls, ls->current, seminfo); + return TK_STRING; + } + case '.': { /* '.', '..', '...', or number */ + save_and_next(ls); + if (check_next(ls, ".")) { + if (check_next(ls, ".")) + return TK_DOTS; /* '...' */ + else + return TK_CONCAT; /* '..' */ + } + else if (!isdigit(ls->current)) + return '.'; + /* else go through */ + } + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + read_numeral(ls, seminfo); + return TK_NUMBER; + } + case EOZ: { + return TK_EOS; + } + case '&': { + next(ls); + if (ls->current != '&') + return '&'; + else { + next(ls); + return TK_AND; + } + } + case '|': { + next(ls); + if (ls->current != '|') + return '|'; + else { + next(ls); + return TK_OR; + } + } + default: { + if (islalpha(ls->current)) { + /* identifier or reserved word? */ + ktap_string *ts; + do { + save_and_next(ls); + } while (islalnum(ls->current)); + ts = lex_newstring(ls, mbuff(ls->buff), + mbuff_len(ls->buff)); + seminfo->ts = ts; + if (isreserved(ts)) /* reserved word? */ + return ts->tsv.extra - 1 + + FIRST_RESERVED; + else { + return TK_NAME; + } + } else { /* single-char tokens (+ - / ...) */ + int c = ls->current; + next(ls); + return c; + } + } + } + } +} + +void lex_read_string_until(ktap_lexstate *ls, int c) +{ + ktap_string *ts; + char errmsg[32]; + + mbuff_reset(ls->buff); + + while (ls->current == ' ') + next(ls); + + do { + save_and_next(ls); + } while (ls->current != c && ls->current != EOZ); + + if (ls->current != c) { + sprintf(errmsg, "expect %c", c); + lexerror(ls, errmsg, 0); + } + + ts = lex_newstring(ls, mbuff(ls->buff), mbuff_len(ls->buff)); + ls->t.seminfo.ts = ts; + ls->t.token = TK_STRING; +} + +void lex_next(ktap_lexstate *ls) +{ + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } else + ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ +} + +int lex_lookahead(ktap_lexstate *ls) +{ + ktap_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); + return ls->lookahead.token; +} + diff --git a/drivers/staging/ktap/userspace/main.c b/drivers/staging/ktap/userspace/main.c new file mode 100644 index 000000000000..2aa686a99914 --- /dev/null +++ b/drivers/staging/ktap/userspace/main.c @@ -0,0 +1,609 @@ +/* + * main.c - ktap compiler and loader entry + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <stdio.h> +#include <stdlib.h> +#include <sched.h> +#include <string.h> +#include <signal.h> +#include <stdarg.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#include <math.h> + +#include "../include/ktap_types.h" +#include "../include/ktap_opcodes.h" +#include "ktapc.h" + + +/*******************************************************************/ + +void *ktapc_reallocv(void *block, size_t osize, size_t nsize) +{ + return kp_reallocv(NULL, block, osize, nsize); +} + +ktap_closure *ktapc_newlclosure(int n) +{ + return kp_newlclosure(NULL, n); +} + +ktap_proto *ktapc_newproto() +{ + return kp_newproto(NULL); +} + +const ktap_value *ktapc_table_get(ktap_table *t, const ktap_value *key) +{ + return kp_table_get(t, key); +} + +void ktapc_table_setvalue(ktap_table *t, const ktap_value *key, ktap_value *val) +{ + kp_table_setvalue(NULL, t, key, val); +} + +ktap_table *ktapc_table_new() +{ + return kp_table_new(NULL); +} + +ktap_string *ktapc_ts_newlstr(const char *str, size_t l) +{ + return kp_tstring_newlstr(NULL, str, l); +} + +ktap_string *ktapc_ts_new(const char *str) +{ + return kp_tstring_new(NULL, str); +} + +int ktapc_ts_eqstr(ktap_string *a, ktap_string *b) +{ + return kp_tstring_eqstr(a, b); +} + +static void ktapc_runerror(const char *err_msg_fmt, ...) +{ + va_list ap; + + fprintf(stderr, "ktapc_runerror\n"); + + va_start(ap, err_msg_fmt); + vfprintf(stderr, err_msg_fmt, ap); + va_end(ap); + + exit(EXIT_FAILURE); +} + +/* + * todo: memory leak here + */ +char *ktapc_sprintf(const char *fmt, ...) +{ + char *msg = malloc(128); + + va_list argp; + va_start(argp, fmt); + vsprintf(msg, fmt, argp); + va_end(argp); + return msg; +} + + +#define MINSIZEARRAY 4 + +void *ktapc_growaux(void *block, int *size, size_t size_elems, int limit, + const char *what) +{ + void *newblock; + int newsize; + + if (*size >= limit/2) { /* cannot double it? */ + if (*size >= limit) /* cannot grow even a little? */ + ktapc_runerror("too many %s (limit is %d)\n", + what, limit); + newsize = limit; /* still have at least one free place */ + } else { + newsize = (*size) * 2; + if (newsize < MINSIZEARRAY) + newsize = MINSIZEARRAY; /* minimum size */ + } + + newblock = ktapc_reallocv(block, (*size) * size_elems, newsize * size_elems); + *size = newsize; /* update only when everything else is OK */ + return newblock; +} + +/*************************************************************************/ + +#define print_base(i) \ + do { \ + if (i < f->sizelocvars) /* it's a localvars */ \ + printf("%s", getstr(f->locvars[i].varname)); \ + else \ + printf("base + %d", i); \ + } while (0) + +#define print_RKC(instr) \ + do { \ + if (ISK(GETARG_C(instr))) \ + kp_showobj(NULL, k + INDEXK(GETARG_C(instr))); \ + else \ + print_base(GETARG_C(instr)); \ + } while (0) + +static void decode_instruction(ktap_proto *f, int instr) +{ + int opcode = GET_OPCODE(instr); + ktap_value *k; + + k = f->k; + + printf("%.8x\t", instr); + printf("%s\t", ktap_opnames[opcode]); + + switch (opcode) { + case OP_GETTABUP: + print_base(GETARG_A(instr)); + printf(" <- "); + + if (GETARG_B(instr) == 0) + printf("global"); + else + printf("upvalues[%d]", GETARG_B(instr)); + + printf("{"); print_RKC(instr); printf("}"); + + break; + case OP_GETTABLE: + print_base(GETARG_A(instr)); + printf(" <- "); + + print_base(GETARG_B(instr)); + + printf("{"); + print_RKC(instr); + printf("}"); + break; + case OP_LOADK: + printf("\t"); + print_base(GETARG_A(instr)); + printf(" <- "); + + kp_showobj(NULL, k + GETARG_Bx(instr)); + break; + case OP_CALL: + printf("\t"); + print_base(GETARG_A(instr)); + break; + case OP_JMP: + printf("\t%d", GETARG_sBx(instr)); + break; + default: + break; + } + + printf("\n"); +} + +static int function_nr = 0; + +/* this is a debug function used for check bytecode chunk file */ +static void dump_function(int level, ktap_proto *f) +{ + int i; + + printf("\n----------------------------------------------------\n"); + printf("function %d [level %d]:\n", function_nr++, level); + printf("linedefined: %d\n", f->linedefined); + printf("lastlinedefined: %d\n", f->lastlinedefined); + printf("numparams: %d\n", f->numparams); + printf("is_vararg: %d\n", f->is_vararg); + printf("maxstacksize: %d\n", f->maxstacksize); + printf("source: %s\n", getstr(f->source)); + printf("sizelineinfo: %d \t", f->sizelineinfo); + for (i = 0; i < f->sizelineinfo; i++) + printf("%d ", f->lineinfo[i]); + printf("\n"); + + printf("sizek: %d\n", f->sizek); + for (i = 0; i < f->sizek; i++) { + switch(f->k[i].type) { + case KTAP_TNIL: + printf("\tNIL\n"); + break; + case KTAP_TBOOLEAN: + printf("\tBOOLEAN: "); + printf("%d\n", f->k[i].val.b); + break; + case KTAP_TNUMBER: + printf("\tTNUMBER: "); + printf("%ld\n", f->k[i].val.n); + break; + case KTAP_TSTRING: + printf("\tTSTRING: "); + printf("%s\n", svalue(&(f->k[i]))); + + break; + default: + printf("\terror: unknow constant type\n"); + } + } + + printf("sizelocvars: %d\n", f->sizelocvars); + for (i = 0; i < f->sizelocvars; i++) { + printf("\tlocvars: %s startpc: %d endpc: %d\n", + getstr(f->locvars[i].varname), f->locvars[i].startpc, + f->locvars[i].endpc); + } + + printf("sizeupvalues: %d\n", f->sizeupvalues); + for (i = 0; i < f->sizeupvalues; i++) { + printf("\tname: %s instack: %d idx: %d\n", + getstr(f->upvalues[i].name), f->upvalues[i].instack, + f->upvalues[i].idx); + } + + printf("\n"); + printf("sizecode: %d\n", f->sizecode); + for (i = 0; i < f->sizecode; i++) + decode_instruction(f, f->code[i]); + + printf("sizep: %d\n", f->sizep); + for (i = 0; i < f->sizep; i++) + dump_function(level + 1, f->p[i]); + +} + +static void usage(const char *msg_fmt, ...) +{ + va_list ap; + + va_start(ap, msg_fmt); + fprintf(stderr, msg_fmt, ap); + va_end(ap); + + fprintf(stderr, +"Usage: ktap [options] file [script args] -- cmd [args]\n" +" or: ktap [options] -e one-liner -- cmd [args]\n" +"\n" +"Options and arguments:\n" +" -o file : send script output to file, instead of stderr\n" +" -p pid : specific tracing pid\n" +" -C cpu : cpu to monitor in system-wide\n" +" -T : show timestamp for event\n" +" -V : show version\n" +" -v : enable verbose mode\n" +" -s : simple event tracing\n" +" -b : list byte codes\n" +" file : program read from script file\n" +" -- cmd [args] : workload to tracing\n"); + + exit(EXIT_FAILURE); +} + +ktap_global_state dummy_global_state; + +static void init_dummy_global_state() +{ + memset(&dummy_global_state, 0, sizeof(ktap_global_state)); + dummy_global_state.seed = 201236; + + kp_tstring_resize(NULL, 32); /* set inital string hashtable size */ +} + +#define handle_error(str) do { perror(str); exit(-1); } while(0) + +static struct ktap_parm uparm; +static int ktap_trunk_mem_size = 1024; + +static int ktapc_writer(const void* p, size_t sz, void* ud) +{ + if (uparm.trunk_len + sz > ktap_trunk_mem_size) { + int new_size = (uparm.trunk_len + sz) * 2; + uparm.trunk = realloc(uparm.trunk, new_size); + ktap_trunk_mem_size = new_size; + } + + memcpy(uparm.trunk + uparm.trunk_len, p, sz); + uparm.trunk_len += sz; + + return 0; +} + + +static int forks; +static char **workload_argv; + +static int fork_workload(int ktap_fd) +{ + int pid; + + pid = fork(); + if (pid < 0) + handle_error("failed to fork"); + + if (pid > 0) + return pid; + + signal(SIGTERM, SIG_DFL); + + execvp("", workload_argv); + + /* + * waiting ktapvm prepare all tracing event + * make it more robust in future. + */ + pause(); + + execvp(workload_argv[0], workload_argv); + + perror(workload_argv[0]); + exit(-1); + + return -1; +} + +#define KTAPVM_PATH "/sys/kernel/debug/ktap/ktapvm" + +static char *output_filename; +pid_t ktap_pid; + +static int run_ktapvm() +{ + int ktapvm_fd, ktap_fd; + int ret; + + ktap_pid = getpid(); + + ktapvm_fd = open(KTAPVM_PATH, O_RDONLY); + if (ktapvm_fd < 0) + handle_error("open " KTAPVM_PATH " failed"); + + ktap_fd = ioctl(ktapvm_fd, 0, NULL); + if (ktap_fd < 0) + handle_error("ioctl ktapvm failed"); + + ktapio_create(output_filename); + + if (forks) { + uparm.trace_pid = fork_workload(ktap_fd); + uparm.workload = 1; + } + + ret = ioctl(ktap_fd, KTAP_CMD_IOC_RUN, &uparm); + + close(ktap_fd); + close(ktapvm_fd); + + return ret; +} + +int verbose; +static int dump_bytecode; +static char oneline_src[1024]; +static int trace_pid = -1; +static int trace_cpu = -1; +static int print_timestamp; + +#define SIMPLE_ONE_LINER_FMT \ + "trace %s { print(cpu(), tid(), execname(), argevent) }" + +static const char *script_file; +static int script_args_start; +static int script_args_end; + +static void parse_option(int argc, char **argv) +{ + char pid[32] = {0}; + char cpu_str[32] = {0}; + char *next_arg; + int i, j; + + for (i = 1; i < argc; i++) { + if (argv[i][0] != '-') { + script_file = argv[i]; + if (!script_file) + usage(""); + + script_args_start = i + 1; + script_args_end = argc; + + for (j = i + 1; j < argc; j++) { + if (argv[j][0] == '-' && argv[j][1] == '-') + goto found_cmd; + } + + return; + } + + if (argv[i][0] == '-' && argv[i][1] == '-') { + j = i; + goto found_cmd; + } + + next_arg = argv[i + 1]; + + switch (argv[i][1]) { + case 'o': + output_filename = malloc(strlen(next_arg) + 1); + if (!output_filename) + return; + + strncpy(output_filename, next_arg, strlen(next_arg)); + i++; + break; + case 'e': + strncpy(oneline_src, next_arg, strlen(next_arg)); + i++; + break; + case 'p': + strncpy(pid, next_arg, strlen(next_arg)); + trace_pid = atoi(pid); + i++; + break; + case 'C': + strncpy(cpu_str, next_arg, strlen(next_arg)); + trace_cpu = atoi(cpu_str); + i++; + break; + case 'T': + print_timestamp = 1; + break; + case 'v': + verbose = 1; + break; + case 's': + sprintf(oneline_src, SIMPLE_ONE_LINER_FMT, next_arg); + i++; + break; + case 'b': + dump_bytecode = 1; + break; + case 'V': + case '?': + case 'h': + usage(""); + break; + default: + usage("wrong argument\n"); + break; + } + } + + return; + + found_cmd: + script_args_end = j; + forks = 1; + workload_argv = &argv[j + 1]; +} + +static void compile(const char *input) +{ + ktap_closure *cl; + char *buff; + struct stat sb; + int fdin; + + if (oneline_src[0] != '\0') { + init_dummy_global_state(); + cl = ktapc_parser(oneline_src, input); + goto dump; + } + + fdin = open(input, O_RDONLY); + if (fdin < 0) { + fprintf(stderr, "open file %s failed\n", input); + exit(-1); + } + + if (fstat(fdin, &sb) == -1) + handle_error("fstat failed"); + + buff = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fdin, 0); + if (buff == MAP_FAILED) + handle_error("mmap failed"); + + init_dummy_global_state(); + cl = ktapc_parser(buff, input); + + munmap(buff, sb.st_size); + close(fdin); + + dump: + if (dump_bytecode) { + dump_function(1, cl->l.p); + exit(0); + } + + /* ktapc output */ + uparm.trunk = malloc(ktap_trunk_mem_size); + if (!uparm.trunk) + handle_error("malloc failed"); + + ktapc_dump(cl->l.p, ktapc_writer, NULL, 0); +} + +int main(int argc, char **argv) +{ + char **ktapvm_argv; + int new_index, i; + int ret; + + if (argc == 1) + usage(""); + + parse_option(argc, argv); + + if (oneline_src[0] != '\0') + script_file = "one-liner"; + + compile(script_file); + + ktapvm_argv = (char **)malloc(sizeof(char *)*(script_args_end - + script_args_start + 1)); + if (!ktapvm_argv) { + fprintf(stderr, "canno allocate ktapvm_argv\n"); + return -1; + } + + ktapvm_argv[0] = malloc(strlen(script_file) + 1); + if (!ktapvm_argv[0]) { + fprintf(stderr, "canno allocate memory\n"); + return -1; + } + strcpy(ktapvm_argv[0], script_file); + ktapvm_argv[0][strlen(script_file)] = '\0'; + + /* pass rest argv into ktapvm */ + new_index = 1; + for (i = script_args_start; i < script_args_end; i++) { + ktapvm_argv[new_index] = malloc(strlen(argv[i]) + 1); + if (!ktapvm_argv[new_index]) { + fprintf(stderr, "canno allocate memory\n"); + return -1; + } + strcpy(ktapvm_argv[new_index], argv[i]); + ktapvm_argv[new_index][strlen(argv[i])] = '\0'; + new_index++; + } + + uparm.argv = ktapvm_argv; + uparm.argc = new_index; + uparm.verbose = verbose; + uparm.trace_pid = trace_pid; + uparm.trace_cpu = trace_cpu; + uparm.print_timestamp = print_timestamp; + + /* start running into kernel ktapvm */ + ret = run_ktapvm(); + + cleanup_event_resources(); + return ret; +} + + diff --git a/drivers/staging/ktap/userspace/parser.c b/drivers/staging/ktap/userspace/parser.c new file mode 100644 index 000000000000..dd9e2de692ad --- /dev/null +++ b/drivers/staging/ktap/userspace/parser.c @@ -0,0 +1,1910 @@ +/* + * parser.c - ktap parser + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * Copyright (C) 1994-2013 Lua.org, PUC-Rio. + * - The part of code in this file is copied from lua initially. + * - lua's MIT license is compatible with GPL. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../include/ktap_types.h" +#include "../include/ktap_opcodes.h" +#include "ktapc.h" + +/* maximum number of local variables per function (must be smaller + than 250, due to the bytecode format) */ +#define MAXVARS 200 + +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) + + +/* + * nodes for block list (list of active blocks) + */ +typedef struct ktap_blockcnt { + struct ktap_blockcnt *previous; /* chain */ + short firstlabel; /* index of first label in this block */ + short firstgoto; /* index of first pending goto in this block */ + u8 nactvar; /* # active locals outside the block */ + u8 upval; /* true if some variable in the block is an upvalue */ + u8 isloop; /* true if `block' is a loop */ +} ktap_blockcnt; + +/* + * prototypes for recursive non-terminal functions + */ +static void statement (ktap_lexstate *ls); +static void expr (ktap_lexstate *ls, ktap_expdesc *v); + +static void anchor_token(ktap_lexstate *ls) +{ + /* last token from outer function must be EOS */ + ktap_assert((int)(ls->fs != NULL) || ls->t.token == TK_EOS); + if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { + ktap_string *ts = ls->t.seminfo.ts; + lex_newstring(ls, getstr(ts), ts->tsv.len); + } +} + +/* semantic error */ +static void semerror(ktap_lexstate *ls, const char *msg) +{ + ls->t.token = 0; /* remove 'near to' from final message */ + lex_syntaxerror(ls, msg); +} + +static void error_expected(ktap_lexstate *ls, int token) +{ + lex_syntaxerror(ls, + ktapc_sprintf("%s expected", lex_token2str(ls, token))); +} + +static void errorlimit(ktap_funcstate *fs, int limit, const char *what) +{ + const char *msg; + int line = fs->f->linedefined; + const char *where = (line == 0) ? "main function" + : ktapc_sprintf("function at line %d", line); + + msg = ktapc_sprintf("too many %s (limit is %d) in %s", + what, limit, where); + lex_syntaxerror(fs->ls, msg); +} + +static void checklimit(ktap_funcstate *fs, int v, int l, const char *what) +{ + if (v > l) + errorlimit(fs, l, what); +} + +static int testnext(ktap_lexstate *ls, int c) +{ + if (ls->t.token == c) { + lex_next(ls); + return 1; + } + else + return 0; +} + +static void check(ktap_lexstate *ls, int c) +{ + if (ls->t.token != c) + error_expected(ls, c); +} + +static void checknext(ktap_lexstate *ls, int c) +{ + check(ls, c); + lex_next(ls); +} + +#define check_condition(ls,c,msg) { if (!(c)) lex_syntaxerror(ls, msg); } + +static void check_match(ktap_lexstate *ls, int what, int who, int where) +{ + if (!testnext(ls, what)) { + if (where == ls->linenumber) + error_expected(ls, what); + else { + lex_syntaxerror(ls, ktapc_sprintf( + "%s expected (to close %s at line %d)", + lex_token2str(ls, what), + lex_token2str(ls, who), where)); + } + } +} + +static ktap_string *str_checkname(ktap_lexstate *ls) +{ + ktap_string *ts; + + check(ls, TK_NAME); + ts = ls->t.seminfo.ts; + lex_next(ls); + return ts; +} + +static void init_exp(ktap_expdesc *e, expkind k, int i) +{ + e->f = e->t = NO_JUMP; + e->k = k; + e->u.info = i; +} + +static void codestring(ktap_lexstate *ls, ktap_expdesc *e, ktap_string *s) +{ + init_exp(e, VK, codegen_stringK(ls->fs, s)); +} + +static void checkname(ktap_lexstate *ls, ktap_expdesc *e) +{ + codestring(ls, e, str_checkname(ls)); +} + +static int registerlocalvar(ktap_lexstate *ls, ktap_string *varname) +{ + ktap_funcstate *fs = ls->fs; + ktap_proto *f = fs->f; + int oldsize = f->sizelocvars; + + ktapc_growvector(f->locvars, fs->nlocvars, f->sizelocvars, + ktap_locvar, SHRT_MAX, "local variables"); + + while (oldsize < f->sizelocvars) + f->locvars[oldsize++].varname = NULL; + + f->locvars[fs->nlocvars].varname = varname; + return fs->nlocvars++; +} + +static void new_localvar(ktap_lexstate *ls, ktap_string *name) +{ + ktap_funcstate *fs = ls->fs; + ktap_dyndata *dyd = ls->dyd; + int reg = registerlocalvar(ls, name); + + checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, + MAXVARS, "local variables"); + ktapc_growvector(dyd->actvar.arr, dyd->actvar.n + 1, + dyd->actvar.size, ktap_vardesc, MAX_INT, "local variables"); + dyd->actvar.arr[dyd->actvar.n++].idx = (short)reg; +} + +static void new_localvarliteral_(ktap_lexstate *ls, const char *name, size_t sz) +{ + new_localvar(ls, lex_newstring(ls, name, sz)); +} + +#define new_localvarliteral(ls,v) \ + new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) + +static ktap_locvar *getlocvar(ktap_funcstate *fs, int i) +{ + int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; + + ktap_assert(idx < fs->nlocvars); + return &fs->f->locvars[idx]; +} + +static void adjustlocalvars(ktap_lexstate *ls, int nvars) +{ + ktap_funcstate *fs = ls->fs; + + fs->nactvar = (u8)(fs->nactvar + nvars); + for (; nvars; nvars--) { + getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; + } +} + +static void removevars(ktap_funcstate *fs, int tolevel) +{ + fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); + + while (fs->nactvar > tolevel) + getlocvar(fs, --fs->nactvar)->endpc = fs->pc; +} + +static int searchupvalue(ktap_funcstate *fs, ktap_string *name) +{ + int i; + ktap_upvaldesc *up = fs->f->upvalues; + + for (i = 0; i < fs->nups; i++) { + if (ktapc_ts_eqstr(up[i].name, name)) + return i; + } + return -1; /* not found */ +} + +static int newupvalue(ktap_funcstate *fs, ktap_string *name, ktap_expdesc *v) +{ + ktap_proto *f = fs->f; + int oldsize = f->sizeupvalues; + + checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); + ktapc_growvector(f->upvalues, fs->nups, f->sizeupvalues, + ktap_upvaldesc, MAXUPVAL, "upvalues"); + + while (oldsize < f->sizeupvalues) + f->upvalues[oldsize++].name = NULL; + f->upvalues[(int)fs->nups].instack = (v->k == VLOCAL); + f->upvalues[(int)fs->nups].idx = (u8)(v->u.info); + f->upvalues[(int)fs->nups].name = name; + return fs->nups++; +} + +static int searchvar(ktap_funcstate *fs, ktap_string *n) +{ + int i; + + for (i = fs->nactvar-1; i >= 0; i--) { + if (ktapc_ts_eqstr(n, getlocvar(fs, i)->varname)) + return i; + } + return -1; /* not found */ +} + +/* + * Mark block where variable at given level was defined + * (to emit close instructions later). + */ +static void markupval(ktap_funcstate *fs, int level) +{ + ktap_blockcnt *bl = fs->bl; + + while (bl->nactvar > level) + bl = bl->previous; + bl->upval = 1; +} + +/* + * Find variable with given name 'n'. If it is an upvalue, add this + * upvalue into all intermediate functions. + */ +static int singlevaraux(ktap_funcstate *fs, ktap_string *n, ktap_expdesc *var, int base) +{ + if (fs == NULL) /* no more levels? */ + return VVOID; /* default is global */ + else { + int v = searchvar(fs, n); /* look up locals at current level */ + if (v >= 0) { /* found? */ + init_exp(var, VLOCAL, v); /* variable is local */ + if (!base) + markupval(fs, v); /* local will be used as an upval */ + return VLOCAL; + } else { /* not found as local at current level; try upvalues */ + int idx = searchupvalue(fs, n); /* try existing upvalues */ + if (idx < 0) { /* not found? */ + if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */ + return VVOID; /* not found; is a global */ + /* else was LOCAL or UPVAL */ + idx = newupvalue(fs, n, var); /* will be a new upvalue */ + } + init_exp(var, VUPVAL, idx); + return VUPVAL; + } + } +} + +static void singlevar(ktap_lexstate *ls, ktap_expdesc *var) +{ + ktap_string *varname = str_checkname(ls); + ktap_funcstate *fs = ls->fs; + + if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */ + ktap_expdesc key; + singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ + ktap_assert(var->k == VLOCAL || var->k == VUPVAL); + codestring(ls, &key, varname); /* key is variable name */ + codegen_indexed(fs, var, &key); /* env[varname] */ + } +} + +static void adjust_assign(ktap_lexstate *ls, int nvars, int nexps, ktap_expdesc *e) +{ + ktap_funcstate *fs = ls->fs; + int extra = nvars - nexps; + + if (hasmultret(e->k)) { + extra++; /* includes call itself */ + if (extra < 0) + extra = 0; + codegen_setreturns(fs, e, extra); /* last exp. provides the difference */ + if (extra > 1) + codegen_reserveregs(fs, extra-1); + } else { + if (e->k != VVOID) + codegen_exp2nextreg(fs, e); /* close last expression */ + if (extra > 0) { + int reg = fs->freereg; + + codegen_reserveregs(fs, extra); + codegen_nil(fs, reg, extra); + } + } +} + +static void enterlevel(ktap_lexstate *ls) +{ + ++ls->nCcalls; + checklimit(ls->fs, ls->nCcalls, KTAP_MAXCCALLS, "C levels"); +} + +static void closegoto(ktap_lexstate *ls, int g, ktap_labeldesc *label) +{ + int i; + ktap_funcstate *fs = ls->fs; + ktap_labellist *gl = &ls->dyd->gt; + ktap_labeldesc *gt = &gl->arr[g]; + + ktap_assert(ktapc_ts_eqstr(gt->name, label->name)); + if (gt->nactvar < label->nactvar) { + ktap_string *vname = getlocvar(fs, gt->nactvar)->varname; + const char *msg = ktapc_sprintf( + "<goto %s> at line %d jumps into the scope of local " KTAP_QS, + getstr(gt->name), gt->line, getstr(vname)); + semerror(ls, msg); + } + + codegen_patchlist(fs, gt->pc, label->pc); + /* remove goto from pending list */ + for (i = g; i < gl->n - 1; i++) + gl->arr[i] = gl->arr[i + 1]; + gl->n--; +} + +/* + * try to close a goto with existing labels; this solves backward jumps + */ +static int findlabel(ktap_lexstate *ls, int g) +{ + int i; + ktap_blockcnt *bl = ls->fs->bl; + ktap_dyndata *dyd = ls->dyd; + ktap_labeldesc *gt = &dyd->gt.arr[g]; + + /* check labels in current block for a match */ + for (i = bl->firstlabel; i < dyd->label.n; i++) { + ktap_labeldesc *lb = &dyd->label.arr[i]; + if (ktapc_ts_eqstr(lb->name, gt->name)) { /* correct label? */ + if (gt->nactvar > lb->nactvar && + (bl->upval || dyd->label.n > bl->firstlabel)) + codegen_patchclose(ls->fs, gt->pc, lb->nactvar); + closegoto(ls, g, lb); /* close it */ + return 1; + } + } + return 0; /* label not found; cannot close goto */ +} + +static int newlabelentry(ktap_lexstate *ls, ktap_labellist *l, ktap_string *name, + int line, int pc) +{ + int n = l->n; + + ktapc_growvector(l->arr, n, l->size, + ktap_labeldesc, SHRT_MAX, "labels/gotos"); + l->arr[n].name = name; + l->arr[n].line = line; + l->arr[n].nactvar = ls->fs->nactvar; + l->arr[n].pc = pc; + l->n++; + return n; +} + + +/* + * check whether new label 'lb' matches any pending gotos in current + * block; solves forward jumps + */ +static void findgotos(ktap_lexstate *ls, ktap_labeldesc *lb) +{ + ktap_labellist *gl = &ls->dyd->gt; + int i = ls->fs->bl->firstgoto; + + while (i < gl->n) { + if (ktapc_ts_eqstr(gl->arr[i].name, lb->name)) + closegoto(ls, i, lb); + else + i++; + } +} + +/* + * "export" pending gotos to outer level, to check them against + * outer labels; if the block being exited has upvalues, and + * the goto exits the scope of any variable (which can be the + * upvalue), close those variables being exited. + */ +static void movegotosout(ktap_funcstate *fs, ktap_blockcnt *bl) +{ + int i = bl->firstgoto; + ktap_labellist *gl = &fs->ls->dyd->gt; + + /* correct pending gotos to current block and try to close it + with visible labels */ + while (i < gl->n) { + ktap_labeldesc *gt = &gl->arr[i]; + + if (gt->nactvar > bl->nactvar) { + if (bl->upval) + codegen_patchclose(fs, gt->pc, bl->nactvar); + gt->nactvar = bl->nactvar; + } + if (!findlabel(fs->ls, i)) + i++; /* move to next one */ + } +} + +static void enterblock(ktap_funcstate *fs, ktap_blockcnt *bl, u8 isloop) +{ + bl->isloop = isloop; + bl->nactvar = fs->nactvar; + bl->firstlabel = fs->ls->dyd->label.n; + bl->firstgoto = fs->ls->dyd->gt.n; + bl->upval = 0; + bl->previous = fs->bl; + fs->bl = bl; + ktap_assert(fs->freereg == fs->nactvar); +} + + +/* + * create a label named "break" to resolve break statements + */ +static void breaklabel(ktap_lexstate *ls) +{ + ktap_string *n = ktapc_ts_new("break"); + int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); + + findgotos(ls, &ls->dyd->label.arr[l]); +} + +/* + * generates an error for an undefined 'goto'; choose appropriate + * message when label name is a reserved word (which can only be 'break') + */ +static void undefgoto(ktap_lexstate *ls, ktap_labeldesc *gt) +{ + const char *msg = isreserved(gt->name) + ? "<%s> at line %d not inside a loop" + : "no visible label " KTAP_QS " for <goto> at line %d"; + + msg = ktapc_sprintf(msg, getstr(gt->name), gt->line); + semerror(ls, msg); +} + +static void leaveblock(ktap_funcstate *fs) +{ + ktap_blockcnt *bl = fs->bl; + ktap_lexstate *ls = fs->ls; + if (bl->previous && bl->upval) { + /* create a 'jump to here' to close upvalues */ + int j = codegen_jump(fs); + + codegen_patchclose(fs, j, bl->nactvar); + codegen_patchtohere(fs, j); + } + + if (bl->isloop) + breaklabel(ls); /* close pending breaks */ + + fs->bl = bl->previous; + removevars(fs, bl->nactvar); + ktap_assert(bl->nactvar == fs->nactvar); + fs->freereg = fs->nactvar; /* free registers */ + ls->dyd->label.n = bl->firstlabel; /* remove local labels */ + if (bl->previous) /* inner block? */ + movegotosout(fs, bl); /* update pending gotos to outer block */ + else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ + undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ +} + +/* + * adds a new prototype into list of prototypes + */ +static ktap_proto *addprototype(ktap_lexstate *ls) +{ + ktap_proto *clp; + ktap_funcstate *fs = ls->fs; + ktap_proto *f = fs->f; /* prototype of current function */ + + if (fs->np >= f->sizep) { + int oldsize = f->sizep; + ktapc_growvector(f->p, fs->np, f->sizep, ktap_proto *, MAXARG_Bx, "functions"); + while (oldsize < f->sizep) + f->p[oldsize++] = NULL; + } + f->p[fs->np++] = clp = ktapc_newproto(); + return clp; +} + +/* + * codes instruction to create new closure in parent function + */ +static void codeclosure(ktap_lexstate *ls, ktap_expdesc *v) +{ + ktap_funcstate *fs = ls->fs->prev; + init_exp(v, VRELOCABLE, codegen_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); + codegen_exp2nextreg(fs, v); /* fix it at stack top (for GC) */ +} + +static void open_func(ktap_lexstate *ls, ktap_funcstate *fs, ktap_blockcnt *bl) +{ + ktap_proto *f; + + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + ls->fs = fs; + fs->pc = 0; + fs->lasttarget = 0; + fs->jpc = NO_JUMP; + fs->freereg = 0; + fs->nk = 0; + fs->np = 0; + fs->nups = 0; + fs->nlocvars = 0; + fs->nactvar = 0; + fs->firstlocal = ls->dyd->actvar.n; + fs->bl = NULL; + f = fs->f; + f->source = ls->source; + f->maxstacksize = 2; /* registers 0/1 are always valid */ + fs->h = ktapc_table_new(); + //table_resize(NULL, fs->h, 32, 32); + enterblock(fs, bl, 0); +} + +static void close_func(ktap_lexstate *ls) +{ + ktap_funcstate *fs = ls->fs; + ktap_proto *f = fs->f; + + codegen_ret(fs, 0, 0); /* final return */ + leaveblock(fs); + ktapc_reallocvector(f->code, f->sizecode, fs->pc, ktap_instruction); + f->sizecode = fs->pc; + ktapc_reallocvector(f->lineinfo, f->sizelineinfo, fs->pc, int); + f->sizelineinfo = fs->pc; + ktapc_reallocvector(f->k, f->sizek, fs->nk, ktap_value); + f->sizek = fs->nk; + ktapc_reallocvector(f->p, f->sizep, fs->np, ktap_proto *); + f->sizep = fs->np; + ktapc_reallocvector(f->locvars, f->sizelocvars, fs->nlocvars, ktap_locvar); + f->sizelocvars = fs->nlocvars; + ktapc_reallocvector(f->upvalues, f->sizeupvalues, fs->nups, ktap_upvaldesc); + f->sizeupvalues = fs->nups; + ktap_assert((int)(fs->bl == NULL)); + ls->fs = fs->prev; + /* last token read was anchored in defunct function; must re-anchor it */ + anchor_token(ls); +} + +/*============================================================*/ +/* GRAMMAR RULES */ +/*============================================================*/ + +/* + * check whether current token is in the follow set of a block. + * 'until' closes syntactical blocks, but do not close scope, + * so it handled in separate. + */ +static int block_follow(ktap_lexstate *ls, int withuntil) +{ + switch (ls->t.token) { + case TK_ELSE: case TK_ELSEIF: + case TK_END: case TK_EOS: + return 1; + case TK_UNTIL: + return withuntil; + case '}': + return 1; + default: + return 0; + } +} + +static void statlist(ktap_lexstate *ls) +{ + /* statlist -> { stat [`;'] } */ + while (!block_follow(ls, 1)) { + if (ls->t.token == TK_RETURN) { + statement(ls); + return; /* 'return' must be last statement */ + } + statement(ls); + } +} + +static void fieldsel(ktap_lexstate *ls, ktap_expdesc *v) +{ + /* fieldsel -> ['.' | ':'] NAME */ + ktap_funcstate *fs = ls->fs; + ktap_expdesc key; + + codegen_exp2anyregup(fs, v); + lex_next(ls); /* skip the dot or colon */ + checkname(ls, &key); + codegen_indexed(fs, v, &key); +} + +static void yindex(ktap_lexstate *ls, ktap_expdesc *v) +{ + /* index -> '[' expr ']' */ + lex_next(ls); /* skip the '[' */ + expr(ls, v); + codegen_exp2val(ls->fs, v); + checknext(ls, ']'); +} + +/* + * {====================================================================== + * Rules for Constructors + * ======================================================================= + */ +struct ConsControl { + ktap_expdesc v; /* last list item read */ + ktap_expdesc *t; /* table descriptor */ + int nh; /* total number of `record' elements */ + int na; /* total number of array elements */ + int tostore; /* number of array elements pending to be stored */ +}; + +static void recfield(ktap_lexstate *ls, struct ConsControl *cc) +{ + /* recfield -> (NAME | `['exp1`]') = exp1 */ + ktap_funcstate *fs = ls->fs; + int reg = ls->fs->freereg; + ktap_expdesc key, val; + int rkkey; + + if (ls->t.token == TK_NAME) { + checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + checkname(ls, &key); + } else /* ls->t.token == '[' */ + yindex(ls, &key); + + cc->nh++; + checknext(ls, '='); + rkkey = codegen_exp2RK(fs, &key); + expr(ls, &val); + codegen_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, codegen_exp2RK(fs, &val)); + fs->freereg = reg; /* free registers */ +} + +static void closelistfield(ktap_funcstate *fs, struct ConsControl *cc) +{ + if (cc->v.k == VVOID) + return; /* there is no list item */ + codegen_exp2nextreg(fs, &cc->v); + cc->v.k = VVOID; + if (cc->tostore == LFIELDS_PER_FLUSH) { + codegen_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ + cc->tostore = 0; /* no more items pending */ + } +} + +static void lastlistfield(ktap_funcstate *fs, struct ConsControl *cc) +{ + if (cc->tostore == 0) + return; + + if (hasmultret(cc->v.k)) { + codegen_setmultret(fs, &cc->v); + codegen_setlist(fs, cc->t->u.info, cc->na, KTAP_MULTRET); + cc->na--; /* do not count last expression (unknown number of elements) */ + } else { + if (cc->v.k != VVOID) + codegen_exp2nextreg(fs, &cc->v); + codegen_setlist(fs, cc->t->u.info, cc->na, cc->tostore); + } +} + +static void listfield(ktap_lexstate *ls, struct ConsControl *cc) +{ + /* listfield -> exp */ + expr(ls, &cc->v); + checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + cc->na++; + cc->tostore++; +} + +static void field(ktap_lexstate *ls, struct ConsControl *cc) +{ + /* field -> listfield | recfield */ + switch(ls->t.token) { + case TK_NAME: { /* may be 'listfield' or 'recfield' */ + if (lex_lookahead(ls) != '=') /* expression? */ + listfield(ls, cc); + else + recfield(ls, cc); + break; + } + case '[': { + recfield(ls, cc); + break; + } + default: + listfield(ls, cc); + break; + } +} + +static void constructor(ktap_lexstate *ls, ktap_expdesc *t) +{ + /* constructor -> '{' [ field { sep field } [sep] ] '}' + sep -> ',' | ';' */ + ktap_funcstate *fs = ls->fs; + int line = ls->linenumber; + int pc = codegen_codeABC(fs, OP_NEWTABLE, 0, 0, 0); + struct ConsControl cc; + + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + init_exp(t, VRELOCABLE, pc); + init_exp(&cc.v, VVOID, 0); /* no value (yet) */ + codegen_exp2nextreg(ls->fs, t); /* fix it at stack top */ + checknext(ls, '{'); + do { + ktap_assert(cc.v.k == VVOID || cc.tostore > 0); + if (ls->t.token == '}') + break; + closelistfield(fs, &cc); + field(ls, &cc); + } while (testnext(ls, ',') || testnext(ls, ';')); + check_match(ls, '}', '{', line); + lastlistfield(fs, &cc); + SETARG_B(fs->f->code[pc], ktapc_int2fb(cc.na)); /* set initial array size */ + SETARG_C(fs->f->code[pc], ktapc_int2fb(cc.nh)); /* set initial table size */ +} + +/* }====================================================================== */ + +static void parlist(ktap_lexstate *ls) +{ + /* parlist -> [ param { `,' param } ] */ + ktap_funcstate *fs = ls->fs; + ktap_proto *f = fs->f; + int nparams = 0; + f->is_vararg = 0; + + if (ls->t.token != ')') { /* is `parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_NAME: { /* param -> NAME */ + new_localvar(ls, str_checkname(ls)); + nparams++; + break; + } + case TK_DOTS: { /* param -> `...' */ + lex_next(ls); + f->is_vararg = 1; + break; + } + default: + lex_syntaxerror(ls, "<name> or " KTAP_QL("...") " expected"); + } + } while (!f->is_vararg && testnext(ls, ',')); + } + adjustlocalvars(ls, nparams); + f->numparams = (u8)(fs->nactvar); + codegen_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ +} + +static void body(ktap_lexstate *ls, ktap_expdesc *e, int ismethod, int line) +{ + /* body -> `(' parlist `)' block END */ + ktap_funcstate new_fs; + ktap_blockcnt bl; + + new_fs.f = addprototype(ls); + new_fs.f->linedefined = line; + open_func(ls, &new_fs, &bl); + checknext(ls, '('); + if (ismethod) { + new_localvarliteral(ls, "self"); /* create 'self' parameter */ + adjustlocalvars(ls, 1); + } + parlist(ls); + checknext(ls, ')'); + checknext(ls, '{'); + statlist(ls); + new_fs.f->lastlinedefined = ls->linenumber; + checknext(ls, '}'); + //check_match(ls, TK_END, TK_FUNCTION, line); + codeclosure(ls, e); + close_func(ls); +} + +static void func_body_no_args(ktap_lexstate *ls, ktap_expdesc *e, int line) +{ + /* body -> `(' parlist `)' block END */ + ktap_funcstate new_fs; + ktap_blockcnt bl; + + new_fs.f = addprototype(ls); + new_fs.f->linedefined = line; + open_func(ls, &new_fs, &bl); + checknext(ls, '{'); + statlist(ls); + new_fs.f->lastlinedefined = ls->linenumber; + checknext(ls, '}'); + //check_match(ls, TK_END, TK_FUNCTION, line); + codeclosure(ls, e); + close_func(ls); +} + +static int explist(ktap_lexstate *ls, ktap_expdesc *v) +{ + /* explist -> expr { `,' expr } */ + int n = 1; /* at least one expression */ + + expr(ls, v); + while (testnext(ls, ',')) { + codegen_exp2nextreg(ls->fs, v); + expr(ls, v); + n++; + } + return n; +} + +static void funcargs(ktap_lexstate *ls, ktap_expdesc *f, int line) +{ + ktap_funcstate *fs = ls->fs; + ktap_expdesc args; + int base, nparams; + + switch (ls->t.token) { + case '(': { /* funcargs -> `(' [ explist ] `)' */ + lex_next(ls); + if (ls->t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + explist(ls, &args); + codegen_setmultret(fs, &args); + } + check_match(ls, ')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + codestring(ls, &args, ls->t.seminfo.ts); + lex_next(ls); /* must use `seminfo' before `next' */ + break; + } + default: { + lex_syntaxerror(ls, "function arguments expected"); + } + } + ktap_assert(f->k == VNONRELOC); + base = f->u.info; /* base register for call */ + if (hasmultret(args.k)) + nparams = KTAP_MULTRET; /* open call */ + else { + if (args.k != VVOID) + codegen_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base+1); + } + init_exp(f, VCALL, codegen_codeABC(fs, OP_CALL, base, nparams+1, 2)); + codegen_fixline(fs, line); + fs->freereg = base+1; /* call remove function and arguments and leaves + (unless changed) one result */ +} + +/* + * {====================================================================== + * Expression parsing + * ======================================================================= + */ +static void primaryexp(ktap_lexstate *ls, ktap_expdesc *v) +{ + /* primaryexp -> NAME | '(' expr ')' */ + switch (ls->t.token) { + case '(': { + int line = ls->linenumber; + + lex_next(ls); + expr(ls, v); + check_match(ls, ')', '(', line); + codegen_dischargevars(ls->fs, v); + return; + } + case TK_NAME: + singlevar(ls, v); + return; + default: + lex_syntaxerror(ls, "unexpected symbol"); + } +} + +static void suffixedexp(ktap_lexstate *ls, ktap_expdesc *v) +{ + /* suffixedexp -> + primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ + ktap_funcstate *fs = ls->fs; + int line = ls->linenumber; + + primaryexp(ls, v); + for (;;) { + switch (ls->t.token) { + case '.': { /* fieldsel */ + fieldsel(ls, v); + break; + } + case '[': { /* `[' exp1 `]' */ + ktap_expdesc key; + codegen_exp2anyregup(fs, v); + yindex(ls, &key); + codegen_indexed(fs, v, &key); + break; + } + case ':': { /* `:' NAME funcargs */ + ktap_expdesc key; + lex_next(ls); + checkname(ls, &key); + codegen_self(fs, v, &key); + funcargs(ls, v, line); + break; + } + case '(': case TK_STRING: case '{': { /* funcargs */ + codegen_exp2nextreg(fs, v); + funcargs(ls, v, line); + break; + } + default: + return; + } + } +} + +static void simpleexp(ktap_lexstate *ls, ktap_expdesc *v) +{ + /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | + constructor | FUNCTION body | suffixedexp */ + switch (ls->t.token) { + case TK_NUMBER: { + init_exp(v, VKNUM, 0); + v->u.nval = ls->t.seminfo.r; + break; + } + case TK_STRING: { + codestring(ls, v, ls->t.seminfo.ts); + break; + } + case TK_NIL: { + init_exp(v, VNIL, 0); + break; + } + case TK_TRUE: { + init_exp(v, VTRUE, 0); + break; + } + case TK_FALSE: { + init_exp(v, VFALSE, 0); + break; + } + case TK_DOTS: { /* vararg */ + ktap_funcstate *fs = ls->fs; + check_condition(ls, fs->f->is_vararg, + "cannot use " KTAP_QL("...") " outside a vararg function"); + init_exp(v, VVARARG, codegen_codeABC(fs, OP_VARARG, 0, 1, 0)); + break; + } + case '{': { /* constructor */ + constructor(ls, v); + return; + } + case TK_FUNCTION: { + lex_next(ls); + body(ls, v, 0, ls->linenumber); + return; + } + case TK_ARGEVENT: + init_exp(v, VEVENT, 0); + break; + + case TK_ARGNAME: + init_exp(v, VEVENTNAME, 0); + break; + case TK_ARG1: + case TK_ARG2: + case TK_ARG3: + case TK_ARG4: + case TK_ARG5: + case TK_ARG6: + case TK_ARG7: + case TK_ARG8: + case TK_ARG9: + init_exp(v, VEVENTARG, ls->t.token - TK_ARG1 + 1); + break; + default: { + suffixedexp(ls, v); + return; + } + } + lex_next(ls); +} + +static UnOpr getunopr(int op) +{ + switch (op) { + case TK_NOT: return OPR_NOT; + case '-': return OPR_MINUS; + case '#': return OPR_LEN; + default: return OPR_NOUNOPR; + } +} + +static BinOpr getbinopr(int op) +{ + switch (op) { + case '+': return OPR_ADD; + case '-': return OPR_SUB; + case '*': return OPR_MUL; + case '/': return OPR_DIV; + case '%': return OPR_MOD; + case '^': return OPR_POW; + case TK_CONCAT: return OPR_CONCAT; + case TK_NE: return OPR_NE; + case TK_EQ: return OPR_EQ; + case '<': return OPR_LT; + case TK_LE: return OPR_LE; + case '>': return OPR_GT; + case TK_GE: return OPR_GE; + case TK_AND: return OPR_AND; + case TK_OR: return OPR_OR; + default: return OPR_NOBINOPR; + } +} + +static const struct { + u8 left; /* left priority for each binary operator */ + u8 right; /* right priority */ +} priority[] = { /* ORDER OPR */ + {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `*' `/' `%' */ + {10, 9}, {5, 4}, /* ^, .. (right associative) */ + {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ + {3, 3}, {3, 3}, {3, 3}, /* !=, >, >= */ + {2, 2}, {1, 1} /* and, or */ +}; + +#define UNARY_PRIORITY 8 /* priority for unary operators */ + +#define leavelevel(ls) (ls->nCcalls--) + +/* + * subexpr -> (simpleexp | unop subexpr) { binop subexpr } + * where `binop' is any binary operator with a priority higher than `limit' + */ +static BinOpr subexpr(ktap_lexstate *ls, ktap_expdesc *v, int limit) +{ + BinOpr op; + UnOpr uop; + + enterlevel(ls); + uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) { + int line = ls->linenumber; + + lex_next(ls); + subexpr(ls, v, UNARY_PRIORITY); + codegen_prefix(ls->fs, uop, v, line); + } else + simpleexp(ls, v); + + /* expand while operators have priorities higher than `limit' */ + op = getbinopr(ls->t.token); + while (op != OPR_NOBINOPR && priority[op].left > limit) { + ktap_expdesc v2; + BinOpr nextop; + int line = ls->linenumber; + + lex_next(ls); + codegen_infix(ls->fs, op, v); + /* read sub-expression with higher priority */ + nextop = subexpr(ls, &v2, priority[op].right); + codegen_posfix(ls->fs, op, v, &v2, line); + op = nextop; + } + leavelevel(ls); + return op; /* return first untreated operator */ +} + +static void expr(ktap_lexstate *ls, ktap_expdesc *v) +{ + subexpr(ls, v, 0); +} + +/* }==================================================================== */ + +/* + * {====================================================================== + * Rules for Statements + * ======================================================================= + */ +static void block(ktap_lexstate *ls) +{ + /* block -> statlist */ + ktap_funcstate *fs = ls->fs; + ktap_blockcnt bl; + + enterblock(fs, &bl, 0); + statlist(ls); + leaveblock(fs); +} + +/* + * structure to chain all variables in the left-hand side of an + * assignment + */ +struct LHS_assign { + struct LHS_assign *prev; + ktap_expdesc v; /* variable (global, local, upvalue, or indexed) */ +}; + +/* + * check whether, in an assignment to an upvalue/local variable, the + * upvalue/local variable is begin used in a previous assignment to a + * table. If so, save original upvalue/local value in a safe place and + * use this safe copy in the previous assignment. + */ +static void check_conflict(ktap_lexstate *ls, struct LHS_assign *lh, ktap_expdesc *v) +{ + ktap_funcstate *fs = ls->fs; + int extra = fs->freereg; /* eventual position to save local variable */ + int conflict = 0; + + for (; lh; lh = lh->prev) { /* check all previous assignments */ + if (lh->v.k == VINDEXED) { /* assigning to a table? */ + /* table is the upvalue/local being assigned now? */ + if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { + conflict = 1; + lh->v.u.ind.vt = VLOCAL; + lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ + } + /* index is the local being assigned? (index cannot be upvalue) */ + if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { + conflict = 1; + lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) { + /* copy upvalue/local value to a temporary (in position 'extra') */ + OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + codegen_codeABC(fs, op, extra, v->u.info, 0); + codegen_reserveregs(fs, 1); + } +} + +static void assignment(ktap_lexstate *ls, struct LHS_assign *lh, int nvars) +{ + ktap_expdesc e; + + check_condition(ls, vkisvar(lh->v.k), "syntax error"); + if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ + struct LHS_assign nv; + + nv.prev = lh; + suffixedexp(ls, &nv.v); + if (nv.v.k != VINDEXED) + check_conflict(ls, lh, &nv.v); + checklimit(ls->fs, nvars + ls->nCcalls, KTAP_MAXCCALLS, + "C levels"); + assignment(ls, &nv, nvars+1); + } else if (testnext(ls, '=')) { /* assignment -> '=' explist */ + int nexps; + + nexps = explist(ls, &e); + if (nexps != nvars) { + adjust_assign(ls, nvars, nexps, &e); + /* remove extra values */ + if (nexps > nvars) + ls->fs->freereg -= nexps - nvars; + } else { + /* close last expression */ + codegen_setoneret(ls->fs, &e); + codegen_storevar(ls->fs, &lh->v, &e); + return; /* avoid default */ + } + } else if (testnext(ls, TK_INCR)) { /* assignment -> '+=' explist */ + int nexps; + + nexps = explist(ls, &e); + if (nexps != nvars) { + lex_syntaxerror(ls, "don't allow multi-assign for +="); + } else { + /* close last expression */ + codegen_setoneret(ls->fs, &e); + codegen_storeincr(ls->fs, &lh->v, &e); + return; /* avoid default */ + } + } + + init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ + codegen_storevar(ls->fs, &lh->v, &e); +} + +static int cond(ktap_lexstate *ls) +{ + /* cond -> exp */ + ktap_expdesc v; + expr(ls, &v); /* read condition */ + if (v.k == VNIL) + v.k = VFALSE; /* `falses' are all equal here */ + codegen_goiftrue(ls->fs, &v); + return v.f; +} + +static void gotostat(ktap_lexstate *ls, int pc) +{ + int line = ls->linenumber; + ktap_string *label; + int g; + + if (testnext(ls, TK_GOTO)) + label = str_checkname(ls); + else { + lex_next(ls); /* skip break */ + label = ktapc_ts_new("break"); + } + g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); + findlabel(ls, g); /* close it if label already defined */ +} + +/* check for repeated labels on the same block */ +static void checkrepeated(ktap_funcstate *fs, ktap_labellist *ll, ktap_string *label) +{ + int i; + for (i = fs->bl->firstlabel; i < ll->n; i++) { + if (ktapc_ts_eqstr(label, ll->arr[i].name)) { + const char *msg = ktapc_sprintf( + "label " KTAP_QS " already defined on line %d", + getstr(label), ll->arr[i].line); + semerror(fs->ls, msg); + } + } +} + +/* skip no-op statements */ +static void skipnoopstat(ktap_lexstate *ls) +{ + while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) + statement(ls); +} + +static void labelstat (ktap_lexstate *ls, ktap_string *label, int line) +{ + /* label -> '::' NAME '::' */ + ktap_funcstate *fs = ls->fs; + ktap_labellist *ll = &ls->dyd->label; + int l; /* index of new label being created */ + + checkrepeated(fs, ll, label); /* check for repeated labels */ + checknext(ls, TK_DBCOLON); /* skip double colon */ + /* create new entry for this label */ + l = newlabelentry(ls, ll, label, line, fs->pc); + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ + /* assume that locals are already out of scope */ + ll->arr[l].nactvar = fs->bl->nactvar; + } + findgotos(ls, &ll->arr[l]); +} + +static void whilestat(ktap_lexstate *ls, int line) +{ + /* whilestat -> WHILE cond DO block END */ + ktap_funcstate *fs = ls->fs; + int whileinit; + int condexit; + ktap_blockcnt bl; + + lex_next(ls); /* skip WHILE */ + whileinit = codegen_getlabel(fs); + checknext(ls, '('); + condexit = cond(ls); + checknext(ls, ')'); + + enterblock(fs, &bl, 1); + //checknext(ls, TK_DO); + checknext(ls, '{'); + block(ls); + codegen_jumpto(fs, whileinit); + checknext(ls, '}'); + //check_match(ls, TK_END, TK_WHILE, line); + leaveblock(fs); + codegen_patchtohere(fs, condexit); /* false conditions finish the loop */ +} + +static void repeatstat(ktap_lexstate *ls, int line) +{ + /* repeatstat -> REPEAT block UNTIL cond */ + int condexit; + ktap_funcstate *fs = ls->fs; + int repeat_init = codegen_getlabel(fs); + ktap_blockcnt bl1, bl2; + + enterblock(fs, &bl1, 1); /* loop block */ + enterblock(fs, &bl2, 0); /* scope block */ + lex_next(ls); /* skip REPEAT */ + statlist(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + condexit = cond(ls); /* read condition (inside scope block) */ + if (bl2.upval) /* upvalues? */ + codegen_patchclose(fs, condexit, bl2.nactvar); + leaveblock(fs); /* finish scope */ + codegen_patchlist(fs, condexit, repeat_init); /* close the loop */ + leaveblock(fs); /* finish loop */ +} + +static int exp1(ktap_lexstate *ls) +{ + ktap_expdesc e; + int reg; + + expr(ls, &e); + codegen_exp2nextreg(ls->fs, &e); + ktap_assert(e.k == VNONRELOC); + reg = e.u.info; + return reg; +} + +static void forbody(ktap_lexstate *ls, int base, int line, int nvars, int isnum) +{ + /* forbody -> DO block */ + ktap_blockcnt bl; + ktap_funcstate *fs = ls->fs; + int prep, endfor; + + checknext(ls, ')'); + + adjustlocalvars(ls, 3); /* control variables */ + //checknext(ls, TK_DO); + checknext(ls, '{'); + prep = isnum ? codegen_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : codegen_jump(fs); + enterblock(fs, &bl, 0); /* scope for declared variables */ + adjustlocalvars(ls, nvars); + codegen_reserveregs(fs, nvars); + block(ls); + leaveblock(fs); /* end of scope for declared variables */ + codegen_patchtohere(fs, prep); + if (isnum) /* numeric for? */ + endfor = codegen_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); + else { /* generic for */ + codegen_codeABC(fs, OP_TFORCALL, base, 0, nvars); + codegen_fixline(fs, line); + endfor = codegen_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); + } + codegen_patchlist(fs, endfor, prep + 1); + codegen_fixline(fs, line); +} + +static void fornum(ktap_lexstate *ls, ktap_string *varname, int line) +{ + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + ktap_funcstate *fs = ls->fs; + int base = fs->freereg; + + new_localvarliteral(ls, "(for index)"); + new_localvarliteral(ls, "(for limit)"); + new_localvarliteral(ls, "(for step)"); + new_localvar(ls, varname); + checknext(ls, '='); + exp1(ls); /* initial value */ + checknext(ls, ','); + exp1(ls); /* limit */ + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ + codegen_codek(fs, fs->freereg, codegen_numberK(fs, 1)); + codegen_reserveregs(fs, 1); + } + forbody(ls, base, line, 1, 1); +} + +static void forlist(ktap_lexstate *ls, ktap_string *indexname) +{ + /* forlist -> NAME {,NAME} IN explist forbody */ + ktap_funcstate *fs = ls->fs; + ktap_expdesc e; + int nvars = 4; /* gen, state, control, plus at least one declared var */ + int line; + int base = fs->freereg; + + /* create control variables */ + new_localvarliteral(ls, "(for generator)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for control)"); + /* create declared variables */ + new_localvar(ls, indexname); + while (testnext(ls, ',')) { + new_localvar(ls, str_checkname(ls)); + nvars++; + } + checknext(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, 3, explist(ls, &e), &e); + codegen_checkstack(fs, 3); /* extra space to call generator */ + forbody(ls, base, line, nvars - 3, 0); +} + +static void forstat(ktap_lexstate *ls, int line) +{ + /* forstat -> FOR (fornum | forlist) END */ + ktap_funcstate *fs = ls->fs; + ktap_string *varname; + ktap_blockcnt bl; + + enterblock(fs, &bl, 1); /* scope for loop and control variables */ + lex_next(ls); /* skip `for' */ + + checknext(ls, '('); + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) { + case '=': + fornum(ls, varname, line); + break; + case ',': case TK_IN: + forlist(ls, varname); + break; + default: + lex_syntaxerror(ls, KTAP_QL("=") " or " KTAP_QL("in") " expected"); + } + //check_match(ls, TK_END, TK_FOR, line); + checknext(ls, '}'); + leaveblock(fs); /* loop scope (`break' jumps to this point) */ +} + +static void test_then_block(ktap_lexstate *ls, int *escapelist) +{ + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + ktap_blockcnt bl; + ktap_funcstate *fs = ls->fs; + ktap_expdesc v; + int jf; /* instruction to skip 'then' code (if condition is false) */ + + lex_next(ls); /* skip IF or ELSEIF */ + checknext(ls, '('); + expr(ls, &v); /* read condition */ + checknext(ls, ')'); + //checknext(ls, TK_THEN); + checknext(ls, '{'); + if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { + codegen_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ + enterblock(fs, &bl, 0); /* must enter block before 'goto' */ + gotostat(ls, v.t); /* handle goto/break */ + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ + leaveblock(fs); + checknext(ls, '}'); + return; /* and that is it */ + } else /* must skip over 'then' part if condition is false */ + jf = codegen_jump(fs); + } else { /* regular case (not goto/break) */ + codegen_goiftrue(ls->fs, &v); /* skip over block if condition is false */ + enterblock(fs, &bl, 0); + jf = v.f; + } + statlist(ls); /* `then' part */ + checknext(ls, '}'); + leaveblock(fs); + if (ls->t.token == TK_ELSE || ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ + codegen_concat(fs, escapelist, codegen_jump(fs)); /* must jump over it */ + codegen_patchtohere(fs, jf); +} + +static void ifstat(ktap_lexstate *ls, int line) +{ + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + ktap_funcstate *fs = ls->fs; + int escapelist = NO_JUMP; /* exit list for finished parts */ + + test_then_block(ls, &escapelist); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) + test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ + if (testnext(ls, TK_ELSE)) { + checknext(ls, '{'); + block(ls); /* `else' part */ + checknext(ls, '}'); + } + //check_match(ls, TK_END, TK_IF, line); + codegen_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ +} + +static void localfunc(ktap_lexstate *ls) +{ + ktap_expdesc b; + ktap_funcstate *fs = ls->fs; + + new_localvar(ls, str_checkname(ls)); /* new local variable */ + adjustlocalvars(ls, 1); /* enter its scope */ + body(ls, &b, 0, ls->linenumber); /* function created in next register */ + /* debug information will only see the variable after this point! */ + getlocvar(fs, b.u.info)->startpc = fs->pc; +} + +static void localstat(ktap_lexstate *ls) +{ + /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */ + int nvars = 0; + int nexps; + ktap_expdesc e; + + do { + new_localvar(ls, str_checkname(ls)); + nvars++; + } while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist(ls, &e); + else { + e.k = VVOID; + nexps = 0; + } + adjust_assign(ls, nvars, nexps, &e); + adjustlocalvars(ls, nvars); +} + +static int funcname(ktap_lexstate *ls, ktap_expdesc *v) +{ + /* funcname -> NAME {fieldsel} [`:' NAME] */ + int ismethod = 0; + + singlevar(ls, v); + while (ls->t.token == '.') + fieldsel(ls, v); + if (ls->t.token == ':') { + ismethod = 1; + fieldsel(ls, v); + } + return ismethod; +} + +static void funcstat(ktap_lexstate *ls, int line) +{ + /* funcstat -> FUNCTION funcname body */ + int ismethod; + ktap_expdesc v, b; + + lex_next(ls); /* skip FUNCTION */ + ismethod = funcname(ls, &v); + body(ls, &b, ismethod, line); + codegen_storevar(ls->fs, &v, &b); + codegen_fixline(ls->fs, line); /* definition `happens' in the first line */ +} + +static void exprstat(ktap_lexstate *ls) +{ + /* stat -> func | assignment */ + ktap_funcstate *fs = ls->fs; + struct LHS_assign v; + + suffixedexp(ls, &v.v); + /* stat -> assignment ? */ + if (ls->t.token == '=' || ls->t.token == ',' || + ls->t.token == TK_INCR) { + v.prev = NULL; + assignment(ls, &v, 1); + } else { /* stat -> func */ + check_condition(ls, v.v.k == VCALL, "syntax error"); + SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ + } +} + +static void retstat(ktap_lexstate *ls) +{ + /* stat -> RETURN [explist] [';'] */ + ktap_funcstate *fs = ls->fs; + ktap_expdesc e; + int first, nret; /* registers with returned values */ + + if (block_follow(ls, 1) || ls->t.token == ';') + first = nret = 0; /* return no values */ + else { + nret = explist(ls, &e); /* optional return values */ + if (hasmultret(e.k)) { + codegen_setmultret(fs, &e); + if (e.k == VCALL && nret == 1) { /* tail call? */ + SET_OPCODE(getcode(fs,&e), OP_TAILCALL); + ktap_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); + } + first = fs->nactvar; + nret = KTAP_MULTRET; /* return all values */ + } else { + if (nret == 1) /* only one single value? */ + first = codegen_exp2anyreg(fs, &e); + else { + codegen_exp2nextreg(fs, &e); /* values must go to the `stack' */ + first = fs->nactvar; /* return all `active' values */ + ktap_assert(nret == fs->freereg - first); + } + } + } + codegen_ret(fs, first, nret); + testnext(ls, ';'); /* skip optional semicolon */ +} + +static void tracestat(ktap_lexstate *ls) +{ + ktap_expdesc v0, key, args; + ktap_expdesc *v = &v0; + ktap_string *kdebug_str = ktapc_ts_new("kdebug"); + ktap_string *probe_str = ktapc_ts_new("probe_by_id"); + ktap_string *probe_end_str = ktapc_ts_new("probe_end"); + ktap_funcstate *fs = ls->fs; + int token = ls->t.token; + int line = ls->linenumber; + int base, nparams; + + if (token == TK_TRACE) + lex_read_string_until(ls, '{'); + else + lex_next(ls); /* skip "trace_end" keyword */ + + /* kdebug */ + singlevaraux(fs, ls->envn, v, 1); /* get environment variable */ + codestring(ls, &key, kdebug_str); /* key is variable name */ + codegen_indexed(fs, v, &key); /* env[varname] */ + + /* fieldsel: kdebug.probe */ + codegen_exp2anyregup(fs, v); + if (token == TK_TRACE) + codestring(ls, &key, probe_str); + else if (token == TK_TRACE_END) + codestring(ls, &key, probe_end_str); + codegen_indexed(fs, v, &key); + + /* funcargs*/ + codegen_exp2nextreg(fs, v); + + if (token == TK_TRACE) { + /* argument: EVENTDEF string */ + check(ls, TK_STRING); + enterlevel(ls); + ktap_string *ts = ktapc_parse_eventdef(ls->t.seminfo.ts); + check_condition(ls, ts != NULL, "Cannot parse eventdef"); + codestring(ls, &args, ts); + lex_next(ls); /* skip EVENTDEF string */ + leavelevel(ls); + + codegen_exp2nextreg(fs, &args); /* for next argument */ + } + + /* argument: callback function */ + enterlevel(ls); + func_body_no_args(ls, &args, ls->linenumber); + leavelevel(ls); + + codegen_setmultret(fs, &args); + + base = v->u.info; /* base register for call */ + if (hasmultret(args.k)) + nparams = KTAP_MULTRET; /* open call */ + else { + codegen_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base+1); + } + init_exp(v, VCALL, codegen_codeABC(fs, OP_CALL, base, nparams+1, 2)); + codegen_fixline(fs, line); + fs->freereg = base+1; + + check_condition(ls, v->k == VCALL, "syntax error"); + SETARG_C(getcode(fs, v), 1); /* call statement uses no results */ +} + +static void timerstat(ktap_lexstate *ls) +{ + ktap_expdesc v0, key, args; + ktap_expdesc *v = &v0; + ktap_funcstate *fs = ls->fs; + ktap_string *token_str = ls->t.seminfo.ts; + ktap_string *interval_str; + int line = ls->linenumber; + int base, nparams; + + lex_next(ls); /* skip profile/tick keyword */ + check(ls, '-'); + + lex_read_string_until(ls, '{'); + interval_str = ls->t.seminfo.ts; + + //printf("timerstat str: %s\n", getstr(interval_str)); + //exit(0); + + /* timer */ + singlevaraux(fs, ls->envn, v, 1); /* get environment variable */ + codestring(ls, &key, ktapc_ts_new("timer")); /* key is variable name */ + codegen_indexed(fs, v, &key); /* env[varname] */ + + /* fieldsel: timer.profile, timer.tick */ + codegen_exp2anyregup(fs, v); + codestring(ls, &key, token_str); + codegen_indexed(fs, v, &key); + + /* funcargs*/ + codegen_exp2nextreg(fs, v); + + /* argument: interval string */ + check(ls, TK_STRING); + enterlevel(ls); + codestring(ls, &args, interval_str); + lex_next(ls); /* skip interval string */ + leavelevel(ls); + + codegen_exp2nextreg(fs, &args); /* for next argument */ + + /* argument: callback function */ + enterlevel(ls); + func_body_no_args(ls, &args, ls->linenumber); + leavelevel(ls); + + codegen_setmultret(fs, &args); + + base = v->u.info; /* base register for call */ + if (hasmultret(args.k)) + nparams = KTAP_MULTRET; /* open call */ + else { + codegen_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base+1); + } + init_exp(v, VCALL, codegen_codeABC(fs, OP_CALL, base, nparams+1, 2)); + codegen_fixline(fs, line); + fs->freereg = base+1; + + check_condition(ls, v->k == VCALL, "syntax error"); + SETARG_C(getcode(fs, v), 1); /* call statement uses no results */ +} + +static void statement(ktap_lexstate *ls) +{ + int line = ls->linenumber; /* may be needed for error messages */ + + enterlevel(ls); + switch (ls->t.token) { + case ';': { /* stat -> ';' (empty statement) */ + lex_next(ls); /* skip ';' */ + break; + } + case TK_IF: { /* stat -> ifstat */ + ifstat(ls, line); + break; + } + case TK_WHILE: { /* stat -> whilestat */ + whilestat(ls, line); + break; + } + case TK_DO: { /* stat -> DO block END */ + lex_next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + break; + } + case TK_FOR: { /* stat -> forstat */ + forstat(ls, line); + break; + } + case TK_REPEAT: { /* stat -> repeatstat */ + repeatstat(ls, line); + break; + } + case TK_FUNCTION: { /* stat -> funcstat */ + funcstat(ls, line); + break; + } + case TK_LOCAL: { /* stat -> localstat */ + lex_next(ls); /* skip LOCAL */ + if (testnext(ls, TK_FUNCTION)) /* local function? */ + localfunc(ls); + else + localstat(ls); + break; + } + case TK_DBCOLON: { /* stat -> label */ + lex_next(ls); /* skip double colon */ + labelstat(ls, str_checkname(ls), line); + break; + } + case TK_RETURN: { /* stat -> retstat */ + lex_next(ls); /* skip RETURN */ + retstat(ls); + break; + } + case TK_BREAK: /* stat -> breakstat */ + case TK_GOTO: { /* stat -> 'goto' NAME */ + gotostat(ls, codegen_jump(ls->fs)); + break; + } + + case TK_TRACE: + case TK_TRACE_END: + tracestat(ls); + break; + case TK_PROFILE: + case TK_TICK: + timerstat(ls); + break; + default: { /* stat -> func | assignment */ + exprstat(ls); + break; + } + } + //ktap_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && + // ls->fs->freereg >= ls->fs->nactvar); + ls->fs->freereg = ls->fs->nactvar; /* free registers */ + leavelevel(ls); +} +/* }====================================================================== */ + +/* + * compiles the main function, which is a regular vararg function with an upvalue + */ +static void mainfunc(ktap_lexstate *ls, ktap_funcstate *fs) +{ + ktap_blockcnt bl; + ktap_expdesc v; + + open_func(ls, fs, &bl); + fs->f->is_vararg = 1; /* main function is always vararg */ + init_exp(&v, VLOCAL, 0); /* create and... */ + newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ + lex_next(ls); /* read first token */ + statlist(ls); /* parse main body */ + check(ls, TK_EOS); + close_func(ls); +} + +ktap_closure *ktapc_parser(char *ptr, const char *name) +{ + ktap_lexstate lexstate; + ktap_funcstate funcstate; + ktap_dyndata dyd; + ktap_mbuffer buff; + int firstchar = *ptr++; + ktap_closure *cl = ktapc_newlclosure(1); /* create main closure */ + + memset(&lexstate, 0, sizeof(ktap_lexstate)); + memset(&funcstate, 0, sizeof(ktap_funcstate)); + funcstate.f = cl->l.p = ktapc_newproto(); + funcstate.f->source = ktapc_ts_new(name); /* create and anchor ktap_string */ + + lex_init(); + + mbuff_init(&buff); + memset(&dyd, 0, sizeof(ktap_dyndata)); + lexstate.buff = &buff; + lexstate.dyd = &dyd; + lex_setinput(&lexstate, ptr, funcstate.f->source, firstchar); + + mainfunc(&lexstate, &funcstate); + + ktap_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); + + /* all scopes should be correctly finished */ + ktap_assert(dyd.actvar.n == 0 && dyd.gt.n == 0 && dyd.label.n == 0); + return cl; +} + diff --git a/drivers/staging/ktap/userspace/util.c b/drivers/staging/ktap/userspace/util.c new file mode 100644 index 000000000000..8124de995be7 --- /dev/null +++ b/drivers/staging/ktap/userspace/util.c @@ -0,0 +1,346 @@ +/* + * util.c + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <[email protected]>. + * + * Copyright (C) 1994-2013 Lua.org, PUC-Rio. + * - The part of code in this file is copied from lua initially. + * - lua's MIT license is compatible with GPL. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope 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 <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include "../include/ktap_types.h" +#include "ktapc.h" + +/* + * converts an integer to a "floating point byte", represented as + * (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if + * eeeee != 0 and (xxx) otherwise. + */ +int ktapc_int2fb(unsigned int x) +{ + int e = 0; /* exponent */ + + if (x < 8) + return x; + while (x >= 0x10) { + x = (x+1) >> 1; + e++; + } + return ((e+1) << 3) | ((int)x - 8); +} + +/* converts back */ +int ktapc_fb2int(int x) +{ + int e = (x >> 3) & 0x1f; + + if (e == 0) + return x; + else + return ((x & 7) + 8) << (e - 1); +} + +int ktapc_ceillog2(unsigned int x) +{ + static const u8 log_2[256] = { + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }; + int l = 0; + + x--; + while (x >= 256) { + l += 8; + x >>= 8; + } + return l + log_2[x]; +} + +ktap_number ktapc_arith(int op, ktap_number v1, ktap_number v2) +{ + switch (op) { + case KTAP_OPADD: return NUMADD(v1, v2); + case KTAP_OPSUB: return NUMSUB(v1, v2); + case KTAP_OPMUL: return NUMMUL(v1, v2); + case KTAP_OPDIV: return NUMDIV(v1, v2); + case KTAP_OPMOD: return NUMMOD(v1, v2); + //case KTAP_OPPOW: return NUMPOW(v1, v2); + case KTAP_OPUNM: return NUMUNM(v1); + default: ktap_assert(0); return 0; + } +} + +int ktapc_hexavalue(int c) +{ + if (isdigit(c)) + return c - '0'; + else + return tolower(c) - 'a' + 10; +} + +static int isneg(const char **s) +{ + if (**s == '-') { + (*s)++; + return 1; + } else if (**s == '+') + (*s)++; + + return 0; +} + +static ktap_number readhexa(const char **s, ktap_number r, int *count) +{ + for (; isxdigit((unsigned char)(**s)); (*s)++) { /* read integer part */ + r = (r * 16.0) + (ktap_number)(ktapc_hexavalue((unsigned char)(**s))); + (*count)++; + } + + return r; +} + +/* + * convert an hexadecimal numeric string to a number, following + * C99 specification for 'strtod' + */ +static ktap_number strx2number(const char *s, char **endptr) +{ + ktap_number r = 0.0; + int e = 0, i = 0; + int neg = 0; /* 1 if number is negative */ + + *endptr = (char *)s; /* nothing is valid yet */ + while (isspace((unsigned char)(*s))) + s++; /* skip initial spaces */ + + neg = isneg(&s); /* check signal */ + if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ + return 0.0; /* invalid format (no '0x') */ + + s += 2; /* skip '0x' */ + r = readhexa(&s, r, &i); /* read integer part */ + if (*s == '.') { + s++; /* skip dot */ + r = readhexa(&s, r, &e); /* read fractional part */ + } + + if (i == 0 && e == 0) + return 0.0; /* invalid format (no digit) */ + e *= -4; /* each fractional digit divides value by 2^-4 */ + *endptr = (char *)s; /* valid up to here */ + + if (*s == 'p' || *s == 'P') { /* exponent part? */ + int exp1 = 0; + int neg1; + + s++; /* skip 'p' */ + neg1 = isneg(&s); /* signal */ + if (!isdigit((unsigned char)(*s))) + goto ret; /* must have at least one digit */ + while (isdigit((unsigned char)(*s))) /* read exponent */ + exp1 = exp1 * 10 + *(s++) - '0'; + if (neg1) exp1 = -exp1; + e += exp1; + } + + *endptr = (char *)s; /* valid up to here */ + ret: + if (neg) + r = -r; + + return ldexp(r, e); +} + +int ktapc_str2d(const char *s, size_t len, ktap_number *result) +{ + char *endptr; + + if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ + return 0; + else if (strpbrk(s, "xX")) /* hexa? */ + *result = strx2number(s, &endptr); + else + *result = strtod(s, &endptr); + + if (endptr == s) + return 0; /* nothing recognized */ + while (isspace((unsigned char)(*endptr))) + endptr++; + return (endptr == s + len); /* OK if no trailing characters */ +} + +/* number of chars of a literal string without the ending \0 */ +#define LL(x) (sizeof(x)/sizeof(char) - 1) + +#define RETS "..." +#define PRE "[string \"" +#define POS "\"]" + +#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) + +void ktapc_chunkid(char *out, const char *source, size_t bufflen) +{ + size_t l = strlen(source); + + if (*source == '=') { /* 'literal' source */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* truncate it */ + addstr(out, source + 1, bufflen - 1); + *out = '\0'; + } + } else if (*source == '@') { /* file name */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* add '...' before rest of name */ + addstr(out, RETS, LL(RETS)); + bufflen -= LL(RETS); + memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); + } + } else { /* string; format as [string "source"] */ + const char *nl = strchr(source, '\n'); /* find first new line (if any) */ + addstr(out, PRE, LL(PRE)); /* add prefix */ + bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ + if (l < bufflen && nl == NULL) { /* small one-line source? */ + addstr(out, source, l); /* keep it */ + } else { + if (nl != NULL) + l = nl - source; /* stop at first newline */ + if (l > bufflen) + l = bufflen; + addstr(out, source, l); + addstr(out, RETS, LL(RETS)); + } + memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); + } +} + + +/* + * strglobmatch is copyed from perf(linux/tools/perf/util/string.c) + */ + +/* Character class matching */ +static bool __match_charclass(const char *pat, char c, const char **npat) +{ + bool complement = false, ret = true; + + if (*pat == '!') { + complement = true; + pat++; + } + if (*pat++ == c) /* First character is special */ + goto end; + + while (*pat && *pat != ']') { /* Matching */ + if (*pat == '-' && *(pat + 1) != ']') { /* Range */ + if (*(pat - 1) <= c && c <= *(pat + 1)) + goto end; + if (*(pat - 1) > *(pat + 1)) + goto error; + pat += 2; + } else if (*pat++ == c) + goto end; + } + if (!*pat) + goto error; + ret = false; + +end: + while (*pat && *pat != ']') /* Searching closing */ + pat++; + if (!*pat) + goto error; + *npat = pat + 1; + return complement ? !ret : ret; + +error: + return false; +} + +/* Glob/lazy pattern matching */ +static bool __match_glob(const char *str, const char *pat, bool ignore_space) +{ + while (*str && *pat && *pat != '*') { + if (ignore_space) { + /* Ignore spaces for lazy matching */ + if (isspace(*str)) { + str++; + continue; + } + if (isspace(*pat)) { + pat++; + continue; + } + } + if (*pat == '?') { /* Matches any single character */ + str++; + pat++; + continue; + } else if (*pat == '[') /* Character classes/Ranges */ + if (__match_charclass(pat + 1, *str, &pat)) { + str++; + continue; + } else + return false; + else if (*pat == '\\') /* Escaped char match as normal char */ + pat++; + if (*str++ != *pat++) + return false; + } + /* Check wild card */ + if (*pat == '*') { + while (*pat == '*') + pat++; + if (!*pat) /* Tail wild card matches all */ + return true; + while (*str) + if (__match_glob(str++, pat, ignore_space)) + return true; + } + return !*str && !*pat; +} + +/** + * strglobmatch - glob expression pattern matching + * @str: the target string to match + * @pat: the pattern string to match + * + * This returns true if the @str matches @pat. @pat can includes wildcards + * ('*','?') and character classes ([CHARS], complementation and ranges are + * also supported). Also, this supports escape character ('\') to use special + * characters as normal character. + * + * Note: if @pat syntax is broken, this always returns false. + */ +bool strglobmatch(const char *str, const char *pat) +{ + return __match_glob(str, pat, false); +} + diff --git a/drivers/staging/line6/midi.c b/drivers/staging/line6/midi.c index e3f9a53dbd96..52da4d9d2164 100644 --- a/drivers/staging/line6/midi.c +++ b/drivers/staging/line6/midi.c @@ -205,7 +205,7 @@ static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream, if (up) line6->line6midi->substream_receive = substream; else - line6->line6midi->substream_receive = 0; + line6->line6midi->substream_receive = NULL; } static struct snd_rawmidi_ops line6_midi_output_ops = { diff --git a/drivers/staging/lustre/lnet/lnet/lo.c b/drivers/staging/lustre/lnet/lnet/lo.c index 670dae34107c..efc798e01934 100644 --- a/drivers/staging/lustre/lnet/lnet/lo.c +++ b/drivers/staging/lustre/lnet/lnet/lo.c @@ -36,16 +36,16 @@ #include <linux/lnet/lib-lnet.h> int -lolnd_send (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) +lolnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg) { - LASSERT (!lntmsg->msg_routing); - LASSERT (!lntmsg->msg_target_is_router); + LASSERT(!lntmsg->msg_routing); + LASSERT(!lntmsg->msg_target_is_router); return lnet_parse(ni, &lntmsg->msg_hdr, ni->ni_nid, lntmsg, 0); } int -lolnd_recv (lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, +lolnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed, unsigned int niov, struct iovec *iov, lnet_kiov_t *kiov, unsigned int offset, unsigned int mlen, unsigned int rlen) @@ -89,20 +89,20 @@ static int lolnd_instanced; void lolnd_shutdown(lnet_ni_t *ni) { - CDEBUG (D_NET, "shutdown\n"); - LASSERT (lolnd_instanced); + CDEBUG(D_NET, "shutdown\n"); + LASSERT(lolnd_instanced); lolnd_instanced = 0; } int -lolnd_startup (lnet_ni_t *ni) +lolnd_startup(lnet_ni_t *ni) { - LASSERT (ni->ni_lnd == &the_lolnd); - LASSERT (!lolnd_instanced); + LASSERT(ni->ni_lnd == &the_lolnd); + LASSERT(!lolnd_instanced); lolnd_instanced = 1; - return (0); + return 0; } lnd_t the_lolnd = { diff --git a/drivers/staging/lustre/lnet/lnet/module.c b/drivers/staging/lustre/lnet/lnet/module.c index afb81755cbad..6db8774ff7b7 100644 --- a/drivers/staging/lustre/lnet/lnet/module.c +++ b/drivers/staging/lustre/lnet/lnet/module.c @@ -37,14 +37,14 @@ #define DEBUG_SUBSYSTEM S_LNET #include <linux/lnet/lib-lnet.h> -static int config_on_load = 0; +static int config_on_load; CFS_MODULE_PARM(config_on_load, "i", int, 0444, "configure network at module load"); static struct mutex lnet_config_mutex; int -lnet_configure (void *arg) +lnet_configure(void *arg) { /* 'arg' only there so I can be passed to cfs_create_thread() */ int rc = 0; @@ -64,7 +64,7 @@ lnet_configure (void *arg) } int -lnet_unconfigure (void) +lnet_unconfigure(void) { int refcount; @@ -124,7 +124,7 @@ init_lnet(void) } rc = libcfs_register_ioctl(&lnet_ioctl_handler); - LASSERT (rc == 0); + LASSERT(rc == 0); if (config_on_load) { /* Have to schedule a separate thread to avoid deadlocking @@ -141,7 +141,7 @@ fini_lnet(void) int rc; rc = libcfs_deregister_ioctl(&lnet_ioctl_handler); - LASSERT (rc == 0); + LASSERT(rc == 0); LNetFini(); } diff --git a/drivers/staging/lustre/lnet/selftest/conrpc.c b/drivers/staging/lustre/lnet/selftest/conrpc.c index cbce662b987b..9a52f25b72e9 100644 --- a/drivers/staging/lustre/lnet/selftest/conrpc.c +++ b/drivers/staging/lustre/lnet/selftest/conrpc.c @@ -75,7 +75,7 @@ lstcon_rpc_done(srpc_client_rpc_t *rpc) if (crpc->crp_stamp == 0) { /* not aborted */ - LASSERT (crpc->crp_status == 0); + LASSERT(crpc->crp_status == 0); crpc->crp_stamp = cfs_time_current(); crpc->crp_status = rpc->crpc_status; @@ -153,7 +153,7 @@ lstcon_rpc_put(lstcon_rpc_t *crpc) srpc_bulk_t *bulk = &crpc->crp_rpc->crpc_bulk; int i; - LASSERT (list_empty(&crpc->crp_link)); + LASSERT(list_empty(&crpc->crp_link)); for (i = 0; i < bulk->bk_niov; i++) { if (bulk->bk_iovs[i].kiov_page == NULL) @@ -187,7 +187,7 @@ lstcon_rpc_post(lstcon_rpc_t *crpc) { lstcon_rpc_trans_t *trans = crpc->crp_trans; - LASSERT (trans != NULL); + LASSERT(trans != NULL); atomic_inc(&trans->tas_remaining); crpc->crp_posted = 1; @@ -289,7 +289,7 @@ lstcon_rpc_trans_abort(lstcon_rpc_trans_t *trans, int error) lstcon_rpc_t *crpc; lstcon_node_t *nd; - list_for_each_entry (crpc, &trans->tas_rpcs_list, crp_link) { + list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) { rpc = crpc->crp_rpc; spin_lock(&rpc->crpc_lock); @@ -330,7 +330,7 @@ lstcon_rpc_trans_check(lstcon_rpc_trans_t *trans) !list_empty(&trans->tas_olink)) /* Not an end session RPC */ return 1; - return (atomic_read(&trans->tas_remaining) == 0) ? 1: 0; + return (atomic_read(&trans->tas_remaining) == 0) ? 1 : 0; } int @@ -349,8 +349,8 @@ lstcon_rpc_trans_postwait(lstcon_rpc_trans_t *trans, int timeout) lstcon_rpc_trans_name(trans->tas_opc)); /* post all requests */ - list_for_each_entry (crpc, &trans->tas_rpcs_list, crp_link) { - LASSERT (!crpc->crp_posted); + list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) { + LASSERT(!crpc->crp_posted); lstcon_rpc_post(crpc); } @@ -390,8 +390,8 @@ lstcon_rpc_get_reply(lstcon_rpc_t *crpc, srpc_msg_t **msgpp) srpc_client_rpc_t *rpc = crpc->crp_rpc; srpc_generic_reply_t *rep; - LASSERT (nd != NULL && rpc != NULL); - LASSERT (crpc->crp_stamp != 0); + LASSERT(nd != NULL && rpc != NULL); + LASSERT(crpc->crp_stamp != 0); if (crpc->crp_status != 0) { *msgpp = NULL; @@ -427,14 +427,14 @@ lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) srpc_msg_t *rep; int error; - LASSERT (stat != NULL); + LASSERT(stat != NULL); memset(stat, 0, sizeof(*stat)); list_for_each_entry(crpc, &trans->tas_rpcs_list, crp_link) { lstcon_rpc_stat_total(stat, 1); - LASSERT (crpc->crp_stamp != 0); + LASSERT(crpc->crp_stamp != 0); error = lstcon_rpc_get_reply(crpc, &rep); if (error != 0) { @@ -455,8 +455,7 @@ lstcon_rpc_trans_stat(lstcon_rpc_trans_t *trans, lstcon_trans_stat_t *stat) lstcon_session_feats_check(trans->tas_features); } - CDEBUG(D_NET, "transaction %s : success %d, failure %d, total %d, " - "RPC error(%d), Framework error(%d)\n", + CDEBUG(D_NET, "transaction %s : success %d, failure %d, total %d, RPC error(%d), Framework error(%d)\n", lstcon_rpc_trans_name(trans->tas_opc), lstcon_rpc_stat_success(stat, 0), lstcon_rpc_stat_failure(stat, 0), @@ -482,7 +481,7 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, struct timeval tv; int error; - LASSERT (head_up != NULL); + LASSERT(head_up != NULL); next = head_up; @@ -498,7 +497,7 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, ent = list_entry(next, lstcon_rpc_ent_t, rpe_link); - LASSERT (crpc->crp_stamp != 0); + LASSERT(crpc->crp_stamp != 0); error = lstcon_rpc_get_reply(crpc, &msg); @@ -532,7 +531,9 @@ lstcon_rpc_trans_interpreter(lstcon_rpc_trans_t *trans, if (readent == NULL) continue; - if ((error = readent(trans->tas_opc, msg, ent)) != 0) + error = readent(trans->tas_opc, msg, ent); + + if (error != 0) return error; } @@ -568,19 +569,19 @@ lstcon_rpc_trans_destroy(lstcon_rpc_trans_t *trans) * user wait for them, just abandon them, they will be recycled * in callback */ - LASSERT (crpc->crp_status != 0); + LASSERT(crpc->crp_status != 0); crpc->crp_node = NULL; crpc->crp_trans = NULL; list_del_init(&crpc->crp_link); - count ++; + count++; spin_unlock(&rpc->crpc_lock); atomic_dec(&trans->tas_remaining); } - LASSERT (atomic_read(&trans->tas_remaining) == 0); + LASSERT(atomic_read(&trans->tas_remaining) == 0); list_del(&trans->tas_link); if (!list_empty(&trans->tas_olink)) @@ -669,14 +670,14 @@ lstcon_batrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, brq->bar_bid = tsb->tsb_id; brq->bar_testidx = tsb->tsb_index; brq->bar_opc = transop == LST_TRANS_TSBRUN ? SRPC_BATCH_OPC_RUN : - (transop == LST_TRANS_TSBSTOP ? SRPC_BATCH_OPC_STOP: + (transop == LST_TRANS_TSBSTOP ? SRPC_BATCH_OPC_STOP : SRPC_BATCH_OPC_QUERY); if (transop != LST_TRANS_TSBRUN && transop != LST_TRANS_TSBSTOP) return 0; - LASSERT (tsb->tsb_index == 0); + LASSERT(tsb->tsb_index == 0); batch = (lstcon_batch_t *)tsb; brq->bar_arg = batch->bat_arg; @@ -710,7 +711,7 @@ lstcon_next_id(int idx, int nkiov, lnet_kiov_t *kiov) i = idx / SFW_ID_PER_PAGE; - LASSERT (i < nkiov); + LASSERT(i < nkiov); pid = (lnet_process_id_packed_t *)page_address(kiov[i].kiov_page); @@ -728,9 +729,9 @@ lstcon_dstnodes_prep(lstcon_group_t *grp, int idx, int end; int i = 0; - LASSERT (dist >= 1); - LASSERT (span >= 1); - LASSERT (grp->grp_nnode >= 1); + LASSERT(dist >= 1); + LASSERT(span >= 1); + LASSERT(grp->grp_nnode >= 1); if (span > grp->grp_nnode) return -EINVAL; @@ -741,11 +742,11 @@ lstcon_dstnodes_prep(lstcon_group_t *grp, int idx, list_for_each_entry(ndl, &grp->grp_ndl_list, ndl_link) { nd = ndl->ndl_node; if (i < start) { - i ++; + i++; continue; } - if (i > (end >= start ? end: grp->grp_nnode)) + if (i > (end >= start ? end : grp->grp_nnode)) break; pid = lstcon_next_id((i - start), nkiov, kiov); @@ -866,7 +867,7 @@ lstcon_testrpc_prep(lstcon_node_t *nd, int transop, unsigned feats, bulk->bk_sink = 0; - LASSERT (transop == LST_TRANS_TSBCLIADD); + LASSERT(transop == LST_TRANS_TSBCLIADD); rc = lstcon_dstnodes_prep(test->tes_dst_grp, test->tes_cliidx++, @@ -942,8 +943,7 @@ lstcon_sesnew_stat_reply(lstcon_rpc_trans_t *trans, } if (reply->msg_ses_feats != trans->tas_features) { - CNETERR("Framework features %x from %s is different with " - "features on this transaction: %x\n", + CNETERR("Framework features %x from %s is different with features on this transaction: %x\n", reply->msg_ses_feats, libcfs_nid2str(nd->nd_id.nid), trans->tas_features); status = mksn_rep->mksn_status = EPROTO; @@ -1107,8 +1107,8 @@ lstcon_rpc_trans_ndlist(struct list_head *ndlist, continue; if (rc < 0) { - CDEBUG(D_NET, "Condition error while creating RPC " - " for transaction %d: %d\n", transop, rc); + CDEBUG(D_NET, "Condition error while creating RPC for transaction %d: %d\n", + transop, rc); break; } @@ -1193,7 +1193,7 @@ lstcon_rpc_pinger(void *arg) trans = console_session.ses_ping; - LASSERT (trans != NULL); + LASSERT(trans != NULL); list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link) { nd = ndl->ndl_node; @@ -1219,8 +1219,8 @@ lstcon_rpc_pinger(void *arg) crpc = &nd->nd_ping; if (crpc->crp_rpc != NULL) { - LASSERT (crpc->crp_trans == trans); - LASSERT (!list_empty(&crpc->crp_link)); + LASSERT(crpc->crp_trans == trans); + LASSERT(!list_empty(&crpc->crp_link)); spin_lock(&crpc->crp_rpc->crpc_lock); @@ -1264,7 +1264,7 @@ lstcon_rpc_pinger(void *arg) lstcon_rpc_trans_addreq(trans, crpc); lstcon_rpc_post(crpc); - count ++; + count++; } if (console_session.ses_expired) { @@ -1286,8 +1286,8 @@ lstcon_rpc_pinger_start(void) stt_timer_t *ptimer; int rc; - LASSERT (list_empty(&console_session.ses_rpc_freelist)); - LASSERT (atomic_read(&console_session.ses_rpc_counter) == 0); + LASSERT(list_empty(&console_session.ses_rpc_freelist)); + LASSERT(atomic_read(&console_session.ses_rpc_counter) == 0); rc = lstcon_rpc_trans_prep(NULL, LST_TRANS_SESPING, &console_session.ses_ping); @@ -1307,7 +1307,7 @@ lstcon_rpc_pinger_start(void) void lstcon_rpc_pinger_stop(void) { - LASSERT (console_session.ses_shutdown); + LASSERT(console_session.ses_shutdown); stt_del_timer(&console_session.ses_ping_timer); @@ -1330,7 +1330,7 @@ lstcon_rpc_cleanup_wait(void) /* Called with hold of global mutex */ - LASSERT (console_session.ses_shutdown); + LASSERT(console_session.ses_shutdown); while (!list_empty(&console_session.ses_trans_list)) { list_for_each(pacer, &console_session.ses_trans_list) { @@ -1345,8 +1345,7 @@ lstcon_rpc_cleanup_wait(void) mutex_unlock(&console_session.ses_mutex); - CWARN("Session is shutting down, " - "waiting for termination of transactions\n"); + CWARN("Session is shutting down, waiting for termination of transactions\n"); cfs_pause(cfs_time_seconds(1)); mutex_lock(&console_session.ses_mutex); @@ -1356,8 +1355,7 @@ lstcon_rpc_cleanup_wait(void) lst_wait_until((atomic_read(&console_session.ses_rpc_counter) == 0), console_session.ses_rpc_lock, - "Network is not accessible or target is down, " - "waiting for %d console RPCs to being recycled\n", + "Network is not accessible or target is down, waiting for %d console RPCs to being recycled\n", atomic_read(&console_session.ses_rpc_counter)); list_add(&zlist, &console_session.ses_rpc_freelist); @@ -1392,6 +1390,6 @@ lstcon_rpc_module_init(void) void lstcon_rpc_module_fini(void) { - LASSERT (list_empty(&console_session.ses_rpc_freelist)); - LASSERT (atomic_read(&console_session.ses_rpc_counter) == 0); + LASSERT(list_empty(&console_session.ses_rpc_freelist)); + LASSERT(atomic_read(&console_session.ses_rpc_counter) == 0); } diff --git a/drivers/staging/lustre/lnet/selftest/console.c b/drivers/staging/lustre/lnet/selftest/console.c index 09e4700af640..f1152e4fbcc4 100644 --- a/drivers/staging/lustre/lnet/selftest/console.c +++ b/drivers/staging/lustre/lnet/selftest/console.c @@ -797,7 +797,7 @@ lstcon_group_info(char *name, lstcon_ndlist_ent_t *gents_p, return rc; } - if (dents_up != 0) { + if (dents_up) { /* verbose query */ rc = lstcon_nodes_getent(&grp->grp_ndl_list, index_p, count_p, dents_up); diff --git a/drivers/staging/lustre/lnet/selftest/timer.c b/drivers/staging/lustre/lnet/selftest/timer.c index 3bf4afb42ffe..82fd363679cb 100644 --- a/drivers/staging/lustre/lnet/selftest/timer.c +++ b/drivers/staging/lustre/lnet/selftest/timer.c @@ -74,14 +74,14 @@ stt_add_timer(stt_timer_t *timer) spin_lock(&stt_data.stt_lock); - LASSERT (stt_data.stt_nthreads > 0); - LASSERT (!stt_data.stt_shuttingdown); - LASSERT (timer->stt_func != NULL); - LASSERT (list_empty(&timer->stt_list)); - LASSERT (cfs_time_after(timer->stt_expires, cfs_time_current_sec())); + LASSERT(stt_data.stt_nthreads > 0); + LASSERT(!stt_data.stt_shuttingdown); + LASSERT(timer->stt_func != NULL); + LASSERT(list_empty(&timer->stt_list)); + LASSERT(cfs_time_after(timer->stt_expires, cfs_time_current_sec())); /* a simple insertion sort */ - list_for_each_prev (pos, STTIMER_SLOT(timer->stt_expires)) { + list_for_each_prev(pos, STTIMER_SLOT(timer->stt_expires)) { stt_timer_t *old = list_entry(pos, stt_timer_t, stt_list); if (cfs_time_aftereq(timer->stt_expires, old->stt_expires)) @@ -102,14 +102,14 @@ stt_add_timer(stt_timer_t *timer) * another CPU. */ int -stt_del_timer (stt_timer_t *timer) +stt_del_timer(stt_timer_t *timer) { int ret = 0; spin_lock(&stt_data.stt_lock); - LASSERT (stt_data.stt_nthreads > 0); - LASSERT (!stt_data.stt_shuttingdown); + LASSERT(stt_data.stt_nthreads > 0); + LASSERT(!stt_data.stt_shuttingdown); if (!list_empty(&timer->stt_list)) { ret = 1; @@ -122,7 +122,7 @@ stt_del_timer (stt_timer_t *timer) /* called with stt_data.stt_lock held */ int -stt_expire_list (struct list_head *slot, cfs_time_t now) +stt_expire_list(struct list_head *slot, cfs_time_t now) { int expired = 0; stt_timer_t *timer; @@ -146,7 +146,7 @@ stt_expire_list (struct list_head *slot, cfs_time_t now) } int -stt_check_timers (cfs_time_t *last) +stt_check_timers(cfs_time_t *last) { int expired = 0; cfs_time_t now; @@ -169,7 +169,7 @@ stt_check_timers (cfs_time_t *last) int -stt_timer_main (void *arg) +stt_timer_main(void *arg) { int rc = 0; UNUSED(arg); @@ -193,7 +193,7 @@ stt_timer_main (void *arg) } int -stt_start_timer_thread (void) +stt_start_timer_thread(void) { struct task_struct *task; @@ -211,7 +211,7 @@ stt_start_timer_thread (void) int -stt_startup (void) +stt_startup(void) { int rc = 0; int i; @@ -227,20 +227,20 @@ stt_startup (void) init_waitqueue_head(&stt_data.stt_waitq); rc = stt_start_timer_thread(); if (rc != 0) - CERROR ("Can't spawn timer thread: %d\n", rc); + CERROR("Can't spawn timer thread: %d\n", rc); return rc; } void -stt_shutdown (void) +stt_shutdown(void) { int i; spin_lock(&stt_data.stt_lock); for (i = 0; i < STTIMER_NSLOTS; i++) - LASSERT (list_empty(&stt_data.stt_hash[i])); + LASSERT(list_empty(&stt_data.stt_hash[i])); stt_data.stt_shuttingdown = 1; diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c index 25099cbe37eb..45315101848c 100644 --- a/drivers/staging/lustre/lustre/fld/fld_cache.c +++ b/drivers/staging/lustre/lustre/fld/fld_cache.c @@ -267,7 +267,7 @@ void fld_cache_punch_hole(struct fld_cache *cache, const seqno_t new_end = range->lsr_end; struct fld_cache_entry *fldt; - OBD_ALLOC_GFP(fldt, sizeof *fldt, GFP_ATOMIC); + OBD_ALLOC_GFP(fldt, sizeof(*fldt), GFP_ATOMIC); if (!fldt) { OBD_FREE_PTR(f_new); /* overlap is not allowed, so dont mess up list. */ diff --git a/drivers/staging/lustre/lustre/include/cl_object.h b/drivers/staging/lustre/lustre/include/cl_object.h index edb40afe66f1..c485206fc6c2 100644 --- a/drivers/staging/lustre/lustre/include/cl_object.h +++ b/drivers/staging/lustre/lustre/include/cl_object.h @@ -3096,13 +3096,13 @@ struct cl_io *cl_io_top(struct cl_io *io); void cl_io_print(const struct lu_env *env, void *cookie, lu_printer_t printer, const struct cl_io *io); -#define CL_IO_SLICE_CLEAN(foo_io, base) \ -do { \ - typeof(foo_io) __foo_io = (foo_io); \ +#define CL_IO_SLICE_CLEAN(foo_io, base) \ +do { \ + typeof(foo_io) __foo_io = (foo_io); \ \ - CLASSERT(offsetof(typeof(*__foo_io), base) == 0); \ - memset(&__foo_io->base + 1, 0, \ - (sizeof *__foo_io) - sizeof __foo_io->base); \ + CLASSERT(offsetof(typeof(*__foo_io), base) == 0); \ + memset(&__foo_io->base + 1, 0, \ + sizeof(*__foo_io) - sizeof(__foo_io->base)); \ } while (0) /** @} cl_io */ diff --git a/drivers/staging/lustre/lustre/include/lclient.h b/drivers/staging/lustre/lustre/include/lclient.h index 9d4011f2908b..27316f7b7a70 100644 --- a/drivers/staging/lustre/lustre/include/lclient.h +++ b/drivers/staging/lustre/lustre/include/lclient.h @@ -388,8 +388,8 @@ __u16 ll_dirent_type_get(struct lu_dirent *ent); __u64 cl_fid_build_ino(const struct lu_fid *fid, int api32); __u32 cl_fid_build_gen(const struct lu_fid *fid); -# define CLOBINVRNT(env, clob, expr) \ - ((void)sizeof(env), (void)sizeof(clob), (void)sizeof !!(expr)) +# define CLOBINVRNT(env, clob, expr) \ + ((void)sizeof(env), (void)sizeof(clob), (void)sizeof(!!(expr))) int cl_init_ea_size(struct obd_export *md_exp, struct obd_export *dt_exp); int cl_ocd_update(struct obd_device *host, diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h index 984235ccd3a5..5ca18d016014 100644 --- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h +++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h @@ -831,9 +831,10 @@ static inline void lu_igif_build(struct lu_fid *fid, __u32 ino, __u32 gen) static inline void fid_cpu_to_le(struct lu_fid *dst, const struct lu_fid *src) { /* check that all fields are converted */ - CLASSERT(sizeof *src == - sizeof fid_seq(src) + - sizeof fid_oid(src) + sizeof fid_ver(src)); + CLASSERT(sizeof(*src) == + sizeof(fid_seq(src)) + + sizeof(fid_oid(src)) + + sizeof(fid_ver(src))); dst->f_seq = cpu_to_le64(fid_seq(src)); dst->f_oid = cpu_to_le32(fid_oid(src)); dst->f_ver = cpu_to_le32(fid_ver(src)); @@ -842,9 +843,10 @@ static inline void fid_cpu_to_le(struct lu_fid *dst, const struct lu_fid *src) static inline void fid_le_to_cpu(struct lu_fid *dst, const struct lu_fid *src) { /* check that all fields are converted */ - CLASSERT(sizeof *src == - sizeof fid_seq(src) + - sizeof fid_oid(src) + sizeof fid_ver(src)); + CLASSERT(sizeof(*src) == + sizeof(fid_seq(src)) + + sizeof(fid_oid(src)) + + sizeof(fid_ver(src))); dst->f_seq = le64_to_cpu(fid_seq(src)); dst->f_oid = le32_to_cpu(fid_oid(src)); dst->f_ver = le32_to_cpu(fid_ver(src)); @@ -853,9 +855,10 @@ static inline void fid_le_to_cpu(struct lu_fid *dst, const struct lu_fid *src) static inline void fid_cpu_to_be(struct lu_fid *dst, const struct lu_fid *src) { /* check that all fields are converted */ - CLASSERT(sizeof *src == - sizeof fid_seq(src) + - sizeof fid_oid(src) + sizeof fid_ver(src)); + CLASSERT(sizeof(*src) == + sizeof(fid_seq(src)) + + sizeof(fid_oid(src)) + + sizeof(fid_ver(src))); dst->f_seq = cpu_to_be64(fid_seq(src)); dst->f_oid = cpu_to_be32(fid_oid(src)); dst->f_ver = cpu_to_be32(fid_ver(src)); @@ -864,9 +867,10 @@ static inline void fid_cpu_to_be(struct lu_fid *dst, const struct lu_fid *src) static inline void fid_be_to_cpu(struct lu_fid *dst, const struct lu_fid *src) { /* check that all fields are converted */ - CLASSERT(sizeof *src == - sizeof fid_seq(src) + - sizeof fid_oid(src) + sizeof fid_ver(src)); + CLASSERT(sizeof(*src) == + sizeof(fid_seq(src)) + + sizeof(fid_oid(src)) + + sizeof(fid_ver(src))); dst->f_seq = be64_to_cpu(fid_seq(src)); dst->f_oid = be32_to_cpu(fid_oid(src)); dst->f_ver = be32_to_cpu(fid_ver(src)); @@ -891,9 +895,11 @@ extern void lustre_swab_lu_seq_range(struct lu_seq_range *range); static inline int lu_fid_eq(const struct lu_fid *f0, const struct lu_fid *f1) { /* Check that there is no alignment padding. */ - CLASSERT(sizeof *f0 == - sizeof f0->f_seq + sizeof f0->f_oid + sizeof f0->f_ver); - return memcmp(f0, f1, sizeof *f0) == 0; + CLASSERT(sizeof(*f0) == + sizeof(f0->f_seq) + + sizeof(f0->f_oid) + + sizeof(f0->f_ver)); + return memcmp(f0, f1, sizeof(*f0)) == 0; } #define __diff_normalize(val0, val1) \ @@ -1638,8 +1644,10 @@ static inline void lmm_oi_cpu_to_le(struct ost_id *dst_oi, /* extern void lustre_swab_lov_mds_md(struct lov_mds_md *llm); */ -#define MAX_MD_SIZE (sizeof(struct lov_mds_md) + 4 * sizeof(struct lov_ost_data)) -#define MIN_MD_SIZE (sizeof(struct lov_mds_md) + 1 * sizeof(struct lov_ost_data)) +#define MAX_MD_SIZE \ + (sizeof(struct lov_mds_md) + 4 * sizeof(struct lov_ost_data)) +#define MIN_MD_SIZE \ + (sizeof(struct lov_mds_md) + 1 * sizeof(struct lov_ost_data)) #define XATTR_NAME_ACL_ACCESS "system.posix_acl_access" #define XATTR_NAME_ACL_DEFAULT "system.posix_acl_default" diff --git a/drivers/staging/lustre/lustre/include/lustre_fid.h b/drivers/staging/lustre/lustre/include/lustre_fid.h index d9d5814e318d..ff119532dafb 100644 --- a/drivers/staging/lustre/lustre/include/lustre_fid.h +++ b/drivers/staging/lustre/lustre/include/lustre_fid.h @@ -590,7 +590,7 @@ fid_build_pdo_res_name(const struct lu_fid *fid, unsigned int hash, static inline void ostid_build_res_name(struct ost_id *oi, struct ldlm_res_id *name) { - memset(name, 0, sizeof *name); + memset(name, 0, sizeof(*name)); if (fid_seq_is_mdt0(ostid_seq(oi))) { name->name[LUSTRE_RES_ID_SEQ_OFF] = ostid_id(oi); name->name[LUSTRE_RES_ID_VER_OID_OFF] = ostid_seq(oi); diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h index a6122559d55d..4fd4af9f29c9 100644 --- a/drivers/staging/lustre/lustre/include/obd.h +++ b/drivers/staging/lustre/lustre/include/obd.h @@ -177,7 +177,7 @@ static inline int lov_stripe_md_cmp(struct lov_stripe_md *m1, * ->lsm_wire contains padding, but it should be zeroed out during * allocation. */ - return memcmp(&m1->lsm_wire, &m2->lsm_wire, sizeof m1->lsm_wire); + return memcmp(&m1->lsm_wire, &m2->lsm_wire, sizeof(m1->lsm_wire)); } static inline int lov_lum_lsm_cmp(struct lov_user_md *lum, diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h index 03e6133ef50f..9697e7faff2f 100644 --- a/drivers/staging/lustre/lustre/include/obd_support.h +++ b/drivers/staging/lustre/lustre/include/obd_support.h @@ -633,8 +633,8 @@ do { \ #define OBD_ALLOC(ptr, size) OBD_ALLOC_GFP(ptr, size, __GFP_IO) #define OBD_ALLOC_WAIT(ptr, size) OBD_ALLOC_GFP(ptr, size, GFP_IOFS) -#define OBD_ALLOC_PTR(ptr) OBD_ALLOC(ptr, sizeof *(ptr)) -#define OBD_ALLOC_PTR_WAIT(ptr) OBD_ALLOC_WAIT(ptr, sizeof *(ptr)) +#define OBD_ALLOC_PTR(ptr) OBD_ALLOC(ptr, sizeof(*(ptr))) +#define OBD_ALLOC_PTR_WAIT(ptr) OBD_ALLOC_WAIT(ptr, sizeof(*(ptr))) #define OBD_CPT_ALLOC_GFP(ptr, cptab, cpt, size, gfp_mask) \ __OBD_MALLOC_VERBOSE(ptr, cptab, cpt, size, gfp_mask) @@ -643,7 +643,7 @@ do { \ OBD_CPT_ALLOC_GFP(ptr, cptab, cpt, size, __GFP_IO) #define OBD_CPT_ALLOC_PTR(ptr, cptab, cpt) \ - OBD_CPT_ALLOC(ptr, cptab, cpt, sizeof *(ptr)) + OBD_CPT_ALLOC(ptr, cptab, cpt, sizeof(*(ptr))) # define __OBD_VMALLOC_VEROBSE(ptr, cptab, cpt, size) \ do { \ @@ -773,7 +773,7 @@ do { \ #define OBD_SLAB_CPT_ALLOC_GFP(ptr, slab, cptab, cpt, size, flags) \ __OBD_SLAB_ALLOC_VERBOSE(ptr, slab, cptab, cpt, size, flags) -#define OBD_FREE_PTR(ptr) OBD_FREE(ptr, sizeof *(ptr)) +#define OBD_FREE_PTR(ptr) OBD_FREE(ptr, sizeof(*(ptr))) #define OBD_SLAB_FREE(ptr, slab, size) \ do { \ @@ -789,19 +789,19 @@ do { \ OBD_SLAB_CPT_ALLOC_GFP(ptr, slab, cptab, cpt, size, __GFP_IO) #define OBD_SLAB_ALLOC_PTR(ptr, slab) \ - OBD_SLAB_ALLOC(ptr, slab, sizeof *(ptr)) + OBD_SLAB_ALLOC(ptr, slab, sizeof(*(ptr))) #define OBD_SLAB_CPT_ALLOC_PTR(ptr, slab, cptab, cpt) \ - OBD_SLAB_CPT_ALLOC(ptr, slab, cptab, cpt, sizeof *(ptr)) + OBD_SLAB_CPT_ALLOC(ptr, slab, cptab, cpt, sizeof(*(ptr))) #define OBD_SLAB_ALLOC_PTR_GFP(ptr, slab, flags) \ - OBD_SLAB_ALLOC_GFP(ptr, slab, sizeof *(ptr), flags) + OBD_SLAB_ALLOC_GFP(ptr, slab, sizeof(*(ptr)), flags) #define OBD_SLAB_CPT_ALLOC_PTR_GFP(ptr, slab, cptab, cpt, flags) \ - OBD_SLAB_CPT_ALLOC_GFP(ptr, slab, cptab, cpt, sizeof *(ptr), flags) + OBD_SLAB_CPT_ALLOC_GFP(ptr, slab, cptab, cpt, sizeof(*(ptr)), flags) #define OBD_SLAB_FREE_PTR(ptr, slab) \ - OBD_SLAB_FREE((ptr), (slab), sizeof *(ptr)) + OBD_SLAB_FREE((ptr), (slab), sizeof(*(ptr))) #define KEY_IS(str) \ (keylen >= (sizeof(str)-1) && memcmp(key, str, (sizeof(str)-1)) == 0) diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c index 8ff38c64b7a1..e60c04d5393a 100644 --- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c +++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c @@ -701,7 +701,7 @@ int ccc_io_one_lock_index(const struct lu_env *env, struct cl_io *io, CDEBUG(D_VFSTRACE, "lock: %d [%lu, %lu]\n", mode, start, end); - memset(&cio->cui_link, 0, sizeof cio->cui_link); + memset(&cio->cui_link, 0, sizeof(cio->cui_link)); if (cio->cui_fd && (cio->cui_fd->fd_flags & LL_FILE_GROUP_LOCKED)) { descr->cld_mode = CLM_GROUP; diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c index 6133b3f34718..027617f5083f 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c @@ -529,7 +529,7 @@ int ldlm_lock_change_resource(struct ldlm_namespace *ns, struct ldlm_lock *lock, lock_res_nested(oldres, LRT_NEW); } LASSERT(memcmp(new_resid, &oldres->lr_name, - sizeof oldres->lr_name) != 0); + sizeof(oldres->lr_name)) != 0); lock->l_resource = newres; unlock_res(oldres); unlock_res_and_lock(lock); diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c index 208751a154b3..8d3dd6dad9b7 100644 --- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c +++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c @@ -1115,7 +1115,7 @@ ldlm_resource_get(struct ldlm_namespace *ns, struct ldlm_resource *parent, lu_ref_fini(&res->lr_reference); /* We have taken lr_lvb_mutex. Drop it. */ mutex_unlock(&res->lr_lvb_mutex); - OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res); + OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof(*res)); res = hlist_entry(hnode, struct ldlm_resource, lr_hash); /* Synchronize with regard to resource creation. */ @@ -1226,7 +1226,7 @@ int ldlm_resource_putref(struct ldlm_resource *res) cfs_hash_bd_unlock(ns->ns_rs_hash, &bd, 1); if (ns->ns_lvbo && ns->ns_lvbo->lvbo_free) ns->ns_lvbo->lvbo_free(res); - OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res); + OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof(*res)); return 1; } return 0; @@ -1256,7 +1256,7 @@ int ldlm_resource_putref_locked(struct ldlm_resource *res) */ if (ns->ns_lvbo && ns->ns_lvbo->lvbo_free) ns->ns_lvbo->lvbo_free(res); - OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof *res); + OBD_SLAB_FREE(res, ldlm_resource_slab, sizeof(*res)); cfs_hash_bd_lock(ns->ns_rs_hash, &bd, 1); return 1; diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c index ab1e73168472..cc565b1fb994 100644 --- a/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c +++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-debug.c @@ -137,7 +137,7 @@ void libcfs_run_lbug_upcall(struct libcfs_debug_msg_data *msgdata) char *argv[6]; char buf[32]; - snprintf (buf, sizeof buf, "%d", msgdata->msg_line); + snprintf(buf, sizeof(buf), "%d", msgdata->msg_line); argv[1] = "LBUG"; argv[2] = (char *)msgdata->msg_file; diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c index 8c4b4fa0d59b..fb85a58db058 100644 --- a/drivers/staging/lustre/lustre/llite/file.c +++ b/drivers/staging/lustre/lustre/llite/file.c @@ -3011,7 +3011,7 @@ static int ll_layout_lock_set(struct lustre_handle *lockh, ldlm_mode_t mode, /* set layout to file. Unlikely this will fail as old layout was * surely eliminated */ - memset(&conf, 0, sizeof conf); + memset(&conf, 0, sizeof(conf)); conf.coc_opc = OBJECT_CONF_SET; conf.coc_inode = inode; conf.coc_lock = lock; @@ -3034,7 +3034,7 @@ out: ll_get_fsname(inode->i_sb, NULL, 0), inode, PFID(&lli->lli_fid)); - memset(&conf, 0, sizeof conf); + memset(&conf, 0, sizeof(conf)); conf.coc_opc = OBJECT_CONF_WAIT; conf.coc_inode = inode; rc = ll_layout_conf(inode, &conf); diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index b868c2bd58d2..fd584ff7e2df 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1973,10 +1973,10 @@ void ll_umount_begin(struct super_block *sb) OBD_ALLOC_PTR(ioc_data); if (ioc_data) { obd_iocontrol(IOC_OSC_SET_ACTIVE, sbi->ll_md_exp, - sizeof *ioc_data, ioc_data, NULL); + sizeof(*ioc_data), ioc_data, NULL); obd_iocontrol(IOC_OSC_SET_ACTIVE, sbi->ll_dt_exp, - sizeof *ioc_data, ioc_data, NULL); + sizeof(*ioc_data), ioc_data, NULL); OBD_FREE_PTR(ioc_data); } diff --git a/drivers/staging/lustre/lustre/llite/rw.c b/drivers/staging/lustre/lustre/llite/rw.c index ae0dc441d1d9..e9ba38a553cf 100644 --- a/drivers/staging/lustre/lustre/llite/rw.c +++ b/drivers/staging/lustre/lustre/llite/rw.c @@ -717,7 +717,7 @@ int ll_readahead(const struct lu_env *env, struct cl_io *io, lli = ll_i2info(inode); clob = lli->lli_clob; - memset(ria, 0, sizeof *ria); + memset(ria, 0, sizeof(*ria)); cl_object_attr_lock(clob); ret = cl_object_attr_get(env, clob, attr); diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c index a4006ef46ad2..099cebb05e44 100644 --- a/drivers/staging/lustre/lustre/lov/lov_dev.c +++ b/drivers/staging/lustre/lustre/lov/lov_dev.c @@ -286,7 +286,7 @@ static void lov_emerg_free(struct lov_device_emerg **emrg, int nr) OBD_FREE_PTR(em); } } - OBD_FREE(emrg, nr * sizeof emrg[0]); + OBD_FREE(emrg, nr * sizeof(emrg[0])); } static struct lu_device *lov_device_free(const struct lu_env *env, @@ -297,7 +297,7 @@ static struct lu_device *lov_device_free(const struct lu_env *env, cl_device_fini(lu2cl_dev(d)); if (ld->ld_target != NULL) - OBD_FREE(ld->ld_target, nr * sizeof ld->ld_target[0]); + OBD_FREE(ld->ld_target, nr * sizeof(ld->ld_target[0])); if (ld->ld_emrg != NULL) lov_emerg_free(ld->ld_emrg, nr); OBD_FREE_PTR(ld); @@ -321,7 +321,7 @@ static struct lov_device_emerg **lov_emerg_alloc(int nr) int i; int result; - OBD_ALLOC(emerg, nr * sizeof emerg[0]); + OBD_ALLOC(emerg, nr * sizeof(emerg[0])); if (emerg == NULL) return ERR_PTR(-ENOMEM); for (result = i = 0; i < nr && result == 0; i++) { @@ -361,7 +361,7 @@ static int lov_expand_targets(const struct lu_env *env, struct lov_device *dev) if (sub_size < tgt_size) { struct lovsub_device **newd; struct lov_device_emerg **emerg; - const size_t sz = sizeof newd[0]; + const size_t sz = sizeof(newd[0]); emerg = lov_emerg_alloc(tgt_size); if (IS_ERR(emerg)) diff --git a/drivers/staging/lustre/lustre/lov/lov_internal.h b/drivers/staging/lustre/lustre/lov/lov_internal.h index 16770d14ee04..9870d360a15a 100644 --- a/drivers/staging/lustre/lustre/lov/lov_internal.h +++ b/drivers/staging/lustre/lustre/lov/lov_internal.h @@ -124,7 +124,7 @@ static inline void lov_llh_put(struct lov_lock_handles *llh) if (atomic_read(&llh->llh_refcount)) return; - OBD_FREE_RCU(llh, sizeof *llh + + OBD_FREE_RCU(llh, sizeof(*llh) + sizeof(*llh->llh_handles) * llh->llh_stripe_count, &llh->llh_handle); } diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c index b611aa4e9dcb..5be0e2c243b0 100644 --- a/drivers/staging/lustre/lustre/lov/lov_io.c +++ b/drivers/staging/lustre/lustre/lov/lov_io.c @@ -282,7 +282,7 @@ static int lov_io_subio_init(const struct lu_env *env, struct lov_io *lio, * when writing a page. -jay */ OBD_ALLOC_LARGE(lio->lis_subs, - lsm->lsm_stripe_count * sizeof lio->lis_subs[0]); + lsm->lsm_stripe_count * sizeof(lio->lis_subs[0])); if (lio->lis_subs != NULL) { lio->lis_nr_subios = lio->lis_stripe_count; lio->lis_single_subio_index = -1; @@ -356,7 +356,7 @@ static void lov_io_fini(const struct lu_env *env, const struct cl_io_slice *ios) for (i = 0; i < lio->lis_nr_subios; i++) lov_io_sub_fini(env, lio, &lio->lis_subs[i]); OBD_FREE_LARGE(lio->lis_subs, - lio->lis_nr_subios * sizeof lio->lis_subs[0]); + lio->lis_nr_subios * sizeof(lio->lis_subs[0])); lio->lis_nr_subios = 0; } diff --git a/drivers/staging/lustre/lustre/lov/lov_lock.c b/drivers/staging/lustre/lustre/lov/lov_lock.c index ec297e87c2a2..7682aeb3fa6a 100644 --- a/drivers/staging/lustre/lustre/lov/lov_lock.c +++ b/drivers/staging/lustre/lustre/lov/lov_lock.c @@ -313,7 +313,7 @@ static int lov_lock_sub_init(const struct lu_env *env, nr++; } LASSERT(nr > 0); - OBD_ALLOC_LARGE(lck->lls_sub, nr * sizeof lck->lls_sub[0]); + OBD_ALLOC_LARGE(lck->lls_sub, nr * sizeof(lck->lls_sub[0])); if (lck->lls_sub == NULL) return -ENOMEM; @@ -474,7 +474,7 @@ static void lov_lock_fini(const struct lu_env *env, */ LASSERT(lck->lls_sub[i].sub_lock == NULL); OBD_FREE_LARGE(lck->lls_sub, - lck->lls_nr * sizeof lck->lls_sub[0]); + lck->lls_nr * sizeof(lck->lls_sub[0])); } OBD_SLAB_FREE_PTR(lck, lov_lock_kmem); } diff --git a/drivers/staging/lustre/lustre/lov/lov_object.c b/drivers/staging/lustre/lustre/lov/lov_object.c index 84e55ce3ccd2..cf2fa8abfb1d 100644 --- a/drivers/staging/lustre/lustre/lov/lov_object.c +++ b/drivers/staging/lustre/lustre/lov/lov_object.c @@ -214,7 +214,7 @@ static int lov_init_raid0(const struct lu_env *env, r0->lo_nr = lsm->lsm_stripe_count; LASSERT(r0->lo_nr <= lov_targets_nr(dev)); - OBD_ALLOC_LARGE(r0->lo_sub, r0->lo_nr * sizeof r0->lo_sub[0]); + OBD_ALLOC_LARGE(r0->lo_sub, r0->lo_nr * sizeof(r0->lo_sub[0])); if (r0->lo_sub != NULL) { result = 0; subconf->coc_inode = conf->coc_inode; @@ -368,7 +368,7 @@ static void lov_fini_raid0(const struct lu_env *env, struct lov_object *lov, struct lov_layout_raid0 *r0 = &state->raid0; if (r0->lo_sub != NULL) { - OBD_FREE_LARGE(r0->lo_sub, r0->lo_nr * sizeof r0->lo_sub[0]); + OBD_FREE_LARGE(r0->lo_sub, r0->lo_nr * sizeof(r0->lo_sub[0])); r0->lo_sub = NULL; } diff --git a/drivers/staging/lustre/lustre/lov/lov_pack.c b/drivers/staging/lustre/lustre/lov/lov_pack.c index 55ec26778f80..2f80833f164a 100644 --- a/drivers/staging/lustre/lustre/lov/lov_pack.c +++ b/drivers/staging/lustre/lustre/lov/lov_pack.c @@ -630,7 +630,7 @@ int lov_getstripe(struct obd_export *exp, struct lov_stripe_md *lsm, /* FIXME: Bug 1185 - copy fields properly when structs change */ /* struct lov_user_md_v3 and struct lov_mds_md_v3 must be the same */ CLASSERT(sizeof(lum) == sizeof(struct lov_mds_md_v3)); - CLASSERT(sizeof lum.lmm_objects[0] == sizeof lmmk->lmm_objects[0]); + CLASSERT(sizeof(lum.lmm_objects[0]) == sizeof(lmmk->lmm_objects[0])); if ((cpu_to_le32(LOV_MAGIC) != LOV_MAGIC) && ((lmmk->lmm_magic == cpu_to_le32(LOV_MAGIC_V1)) || diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c index 61e6d0b46c98..f80e62646683 100644 --- a/drivers/staging/lustre/lustre/lov/lov_request.c +++ b/drivers/staging/lustre/lustre/lov/lov_request.c @@ -245,7 +245,7 @@ int lov_update_enqueue_set(struct lov_request *req, __u32 mode, int rc) osc_update_enqueue(lov_lockhp, loi, oi->oi_flags, &req->rq_oi.oi_md->lsm_oinfo[0]->loi_lvb, mode, rc); if (rc == ELDLM_LOCK_ABORTED && (oi->oi_flags & LDLM_FL_HAS_INTENT)) - memset(lov_lockhp, 0, sizeof *lov_lockhp); + memset(lov_lockhp, 0, sizeof(*lov_lockhp)); rc = lov_update_enqueue_lov(set->set_exp, lov_lockhp, loi, oi->oi_flags, req->rq_idx, &oi->oi_md->lsm_oi, rc); lov_stripe_unlock(oi->oi_md); @@ -343,7 +343,7 @@ static struct lov_lock_handles *lov_llh_new(struct lov_stripe_md *lsm) { struct lov_lock_handles *llh; - OBD_ALLOC(llh, sizeof *llh + + OBD_ALLOC(llh, sizeof(*llh) + sizeof(*llh->llh_handles) * lsm->lsm_stripe_count); if (llh == NULL) return NULL; diff --git a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c index f6268dcec542..ea3771550788 100644 --- a/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c +++ b/drivers/staging/lustre/lustre/lvfs/lvfs_linux.c @@ -282,7 +282,7 @@ __s64 lprocfs_read_helper(struct lprocfs_counter *lc, break; default: break; - }; + } return ret; } diff --git a/drivers/staging/lustre/lustre/obdclass/cl_io.c b/drivers/staging/lustre/lustre/obdclass/cl_io.c index 426979341554..e048500edd60 100644 --- a/drivers/staging/lustre/lustre/obdclass/cl_io.c +++ b/drivers/staging/lustre/lustre/obdclass/cl_io.c @@ -1387,7 +1387,7 @@ static void cl_req_free(const struct lu_env *env, struct cl_req *req) cl_object_put(env, obj); } } - OBD_FREE(req->crq_o, req->crq_nrobjs * sizeof req->crq_o[0]); + OBD_FREE(req->crq_o, req->crq_nrobjs * sizeof(req->crq_o[0])); } OBD_FREE_PTR(req); } @@ -1452,7 +1452,7 @@ struct cl_req *cl_req_alloc(const struct lu_env *env, struct cl_page *page, if (req != NULL) { int result; - OBD_ALLOC(req->crq_o, nr_objects * sizeof req->crq_o[0]); + OBD_ALLOC(req->crq_o, nr_objects * sizeof(req->crq_o[0])); if (req->crq_o != NULL) { req->crq_nrobjs = nr_objects; req->crq_type = crt; @@ -1642,7 +1642,7 @@ int cl_sync_io_wait(const struct lu_env *env, struct cl_io *io, cpu_relax(); } - POISON(anchor, 0x5a, sizeof *anchor); + POISON(anchor, 0x5a, sizeof(*anchor)); return rc; } EXPORT_SYMBOL(cl_sync_io_wait); diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c index b1024a6d37dd..4afd962cdb64 100644 --- a/drivers/staging/lustre/lustre/obdclass/class_obd.c +++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c @@ -178,7 +178,7 @@ EXPORT_SYMBOL(obd_alloc_fail); static inline void obd_data2conn(struct lustre_handle *conn, struct obd_ioctl_data *data) { - memset(conn, 0, sizeof *conn); + memset(conn, 0, sizeof(*conn)); conn->cookie = data->ioc_cookie; } diff --git a/drivers/staging/lustre/lustre/obdclass/llog_test.c b/drivers/staging/lustre/lustre/obdclass/llog_test.c index d9e6d12215f9..178f89eccab1 100644 --- a/drivers/staging/lustre/lustre/obdclass/llog_test.c +++ b/drivers/staging/lustre/lustre/obdclass/llog_test.c @@ -242,7 +242,7 @@ static int llog_test_3(const struct lu_env *env, struct obd_device *obd, hdr.lrh_len = 8; hdr.lrh_type = OBD_CFG_REC; - memset(buf, 0, sizeof buf); + memset(buf, 0, sizeof(buf)); rc = llog_write(env, llh, &hdr, NULL, 0, buf, -1); if (rc < 0) { CERROR("3b: write 10 records failed at #%d: %d\n", @@ -277,8 +277,8 @@ static int llog_test_3(const struct lu_env *env, struct obd_device *obd, char buf_even[24]; char buf_odd[32]; - memset(buf_odd, 0, sizeof buf_odd); - memset(buf_even, 0, sizeof buf_even); + memset(buf_odd, 0, sizeof(buf_odd)); + memset(buf_even, 0, sizeof(buf_even)); if ((i % 2) == 0) { hdr.lrh_len = 24; hdr.lrh_type = OBD_CFG_REC; diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c index 3a3d5bc5a628..e8f260781c0e 100644 --- a/drivers/staging/lustre/lustre/obdclass/lu_object.c +++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c @@ -980,7 +980,7 @@ int lu_site_init(struct lu_site *s, struct lu_device *top) int bits; int i; - memset(s, 0, sizeof *s); + memset(s, 0, sizeof(*s)); bits = lu_htable_order(); snprintf(name, 16, "lu_site_%s", top->ld_type->ldt_name); for (bits = min(max(LU_SITE_BITS_MIN, bits), LU_SITE_BITS_MAX); @@ -1110,7 +1110,7 @@ int lu_device_init(struct lu_device *d, struct lu_device_type *t) { if (t->ldt_device_nr++ == 0 && t->ldt_ops->ldto_start != NULL) t->ldt_ops->ldto_start(t); - memset(d, 0, sizeof *d); + memset(d, 0, sizeof(*d)); atomic_set(&d->ld_ref, 0); d->ld_type = t; lu_ref_init(&d->ld_reference); @@ -1206,7 +1206,7 @@ EXPORT_SYMBOL(lu_object_add); */ int lu_object_header_init(struct lu_object_header *h) { - memset(h, 0, sizeof *h); + memset(h, 0, sizeof(*h)); atomic_set(&h->loh_ref, 1); INIT_HLIST_NODE(&h->loh_hash); INIT_LIST_HEAD(&h->loh_lru); @@ -1525,7 +1525,7 @@ static void keys_fini(struct lu_context *ctx) for (i = 0; i < ARRAY_SIZE(lu_keys); ++i) key_fini(ctx, i); - OBD_FREE(ctx->lc_value, ARRAY_SIZE(lu_keys) * sizeof ctx->lc_value[0]); + OBD_FREE(ctx->lc_value, ARRAY_SIZE(lu_keys) * sizeof(ctx->lc_value[0])); ctx->lc_value = NULL; } @@ -1574,7 +1574,8 @@ static int keys_fill(struct lu_context *ctx) static int keys_init(struct lu_context *ctx) { - OBD_ALLOC(ctx->lc_value, ARRAY_SIZE(lu_keys) * sizeof ctx->lc_value[0]); + OBD_ALLOC(ctx->lc_value, + ARRAY_SIZE(lu_keys) * sizeof(ctx->lc_value[0])); if (likely(ctx->lc_value != NULL)) return keys_fill(ctx); @@ -1588,7 +1589,7 @@ int lu_context_init(struct lu_context *ctx, __u32 tags) { int rc; - memset(ctx, 0, sizeof *ctx); + memset(ctx, 0, sizeof(*ctx)); ctx->lc_state = LCS_INITIALIZED; ctx->lc_tags = tags; if (tags & LCT_REMEMBER) { diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c index d0a64ff53581..73e2571f463f 100644 --- a/drivers/staging/lustre/lustre/obdclass/obd_config.c +++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c @@ -417,7 +417,7 @@ int class_attach(struct lustre_cfg *lcfg) /* do the attach */ if (OBP(obd, attach)) { - rc = OBP(obd,attach)(obd, sizeof *lcfg, lcfg); + rc = OBP(obd, attach)(obd, sizeof(*lcfg), lcfg); if (rc) GOTO(out, rc = -EINVAL); } @@ -900,7 +900,7 @@ void class_del_profile(const char *prof) OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1); if (lprof->lp_md) OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1); - OBD_FREE(lprof, sizeof *lprof); + OBD_FREE(lprof, sizeof(*lprof)); } } EXPORT_SYMBOL(class_del_profile); @@ -916,7 +916,7 @@ void class_del_profiles(void) OBD_FREE(lprof->lp_dt, strlen(lprof->lp_dt) + 1); if (lprof->lp_md) OBD_FREE(lprof->lp_md, strlen(lprof->lp_md) + 1); - OBD_FREE(lprof, sizeof *lprof); + OBD_FREE(lprof, sizeof(*lprof)); } } EXPORT_SYMBOL(class_del_profiles); diff --git a/drivers/staging/lustre/lustre/obdclass/uuid.c b/drivers/staging/lustre/lustre/obdclass/uuid.c index af5f27f82bc5..e87a19900770 100644 --- a/drivers/staging/lustre/lustre/obdclass/uuid.c +++ b/drivers/staging/lustre/lustre/obdclass/uuid.c @@ -48,7 +48,7 @@ static inline __u32 consume(int nob, __u8 **ptr) { __u32 value; - LASSERT(nob <= sizeof value); + LASSERT(nob <= sizeof(value)); for (value = 0; nob > 0; --nob) value = (value << 8) | *((*ptr)++); @@ -61,7 +61,7 @@ static void uuid_unpack(class_uuid_t in, __u16 *uu, int nr) { __u8 *ptr = in; - LASSERT(nr * sizeof *uu == sizeof(class_uuid_t)); + LASSERT(nr * sizeof(*uu) == sizeof(class_uuid_t)); while (nr-- > 0) CONSUME(uu[nr], &ptr); diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c index c8b43442dc74..1fb0ac4e920d 100644 --- a/drivers/staging/lustre/lustre/obdecho/echo_client.c +++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c @@ -1089,7 +1089,7 @@ static struct echo_object *cl_echo_object_find(struct echo_device *d, } else { struct lustre_md *md; md = &info->eti_md; - memset(md, 0, sizeof *md); + memset(md, 0, sizeof(*md)); md->lsm = lsm; conf->eoc_cl.u.coc_md = md; } diff --git a/drivers/staging/lustre/lustre/osc/osc_lock.c b/drivers/staging/lustre/lustre/osc/osc_lock.c index 5d7bdbfc871a..c90abfbb1d7a 100644 --- a/drivers/staging/lustre/lustre/osc/osc_lock.c +++ b/drivers/staging/lustre/lustre/osc/osc_lock.c @@ -862,7 +862,7 @@ static int osc_ldlm_glimpse_ast(struct ldlm_lock *dlmlock, void *data) cap = &req->rq_pill; req_capsule_extend(cap, &RQF_LDLM_GL_CALLBACK); req_capsule_set_size(cap, &RMF_DLM_LVB, RCL_SERVER, - sizeof *lvb); + sizeof(*lvb)); result = req_capsule_server_pack(cap); if (result == 0) { lvb = req_capsule_server_get(cap, &RMF_DLM_LVB); diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c index d272322b29b6..6c20b8ecfb82 100644 --- a/drivers/staging/lustre/lustre/osc/osc_page.c +++ b/drivers/staging/lustre/lustre/osc/osc_page.c @@ -245,7 +245,7 @@ static int osc_page_cache_add(const struct lu_env *env, void osc_index2policy(ldlm_policy_data_t *policy, const struct cl_object *obj, pgoff_t start, pgoff_t end) { - memset(policy, 0, sizeof *policy); + memset(policy, 0, sizeof(*policy)); policy->l_extent.start = cl_offset(obj, start); policy->l_extent.end = cl_offset(obj, end + 1) - 1; } diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c index ee6707a5ea9d..cb197782d9a3 100644 --- a/drivers/staging/lustre/lustre/osc/osc_request.c +++ b/drivers/staging/lustre/lustre/osc/osc_request.c @@ -2554,7 +2554,7 @@ int osc_enqueue_base(struct obd_export *exp, struct ldlm_res_id *res_id, } req_capsule_set_size(&req->rq_pill, &RMF_DLM_LVB, RCL_SERVER, - sizeof *lvb); + sizeof(*lvb)); ptlrpc_request_set_replen(req); } diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c index 810a458caed7..c2ab0c8c4d42 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/client.c +++ b/drivers/staging/lustre/lustre/ptlrpc/client.c @@ -817,7 +817,7 @@ struct ptlrpc_request_set *ptlrpc_prep_set(void) { struct ptlrpc_request_set *set; - OBD_ALLOC(set, sizeof *set); + OBD_ALLOC(set, sizeof(*set)); if (!set) return NULL; atomic_set(&set->set_refcount, 1); @@ -2690,7 +2690,7 @@ int ptlrpc_replay_req(struct ptlrpc_request *req) LASSERT (sizeof (*aa) <= sizeof (req->rq_async_args)); aa = ptlrpc_req_async_args(req); - memset(aa, 0, sizeof *aa); + memset(aa, 0, sizeof(*aa)); /* Prepare request to be resent with ptlrpcd */ aa->praa_old_state = req->rq_send_state; diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c index 5ca69aec72e1..7b96a0e88cdb 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/import.c +++ b/drivers/staging/lustre/lustre/ptlrpc/import.c @@ -682,7 +682,7 @@ int ptlrpc_connect_import(struct obd_import *imp) CLASSERT(sizeof (*aa) <= sizeof (request->rq_async_args)); aa = ptlrpc_req_async_args(request); - memset(aa, 0, sizeof *aa); + memset(aa, 0, sizeof(*aa)); aa->pcaa_peer_committed = committed_before_reconnect; aa->pcaa_initial_connect = initial_connect; diff --git a/drivers/staging/lustre/lustre/ptlrpc/layout.c b/drivers/staging/lustre/lustre/ptlrpc/layout.c index 2f55ce26ccba..d0a6e5689227 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/layout.c +++ b/drivers/staging/lustre/lustre/ptlrpc/layout.c @@ -1669,7 +1669,7 @@ void req_capsule_init(struct req_capsule *pill, if (req != NULL && pill == &req->rq_pill && req->rq_pill_init) return; - memset(pill, 0, sizeof *pill); + memset(pill, 0, sizeof(*pill)); pill->rc_req = req; pill->rc_loc = location; req_capsule_init_area(pill); diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c index acf75f3873d1..21de868da522 100644 --- a/drivers/staging/lustre/lustre/ptlrpc/service.c +++ b/drivers/staging/lustre/lustre/ptlrpc/service.c @@ -263,7 +263,7 @@ static struct ptlrpc_hr_service ptlrpc_hr; */ static void rs_batch_init(struct rs_batch *b) { - memset(b, 0, sizeof *b); + memset(b, 0, sizeof(*b)); INIT_LIST_HEAD(&b->rsb_replies); } @@ -1306,12 +1306,12 @@ static int ptlrpc_at_send_early_reply(struct ptlrpc_request *req) } newdl = cfs_time_current_sec() + at_get(&svcpt->scp_at_estimate); - OBD_ALLOC(reqcopy, sizeof *reqcopy); + OBD_ALLOC(reqcopy, sizeof(*reqcopy)); if (reqcopy == NULL) return -ENOMEM; OBD_ALLOC_LARGE(reqmsg, req->rq_reqlen); if (!reqmsg) { - OBD_FREE(reqcopy, sizeof *reqcopy); + OBD_FREE(reqcopy, sizeof(*reqcopy)); return -ENOMEM; } @@ -1370,7 +1370,7 @@ out_put: out: sptlrpc_svc_ctx_decref(reqcopy); OBD_FREE_LARGE(reqmsg, req->rq_reqlen); - OBD_FREE(reqcopy, sizeof *reqcopy); + OBD_FREE(reqcopy, sizeof(*reqcopy)); return rc; } diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c index 1aa659c04b7a..6f756830c421 100644 --- a/drivers/staging/media/go7007/go7007-usb.c +++ b/drivers/staging/media/go7007/go7007-usb.c @@ -36,10 +36,9 @@ static unsigned int assume_endura; module_param(assume_endura, int, 0644); -MODULE_PARM_DESC(assume_endura, "when probing fails, " - "hardware is a Pelco Endura"); +MODULE_PARM_DESC(assume_endura, + "when probing fails, hardware is a Pelco Endura"); -/* #define GO7007_USB_DEBUG */ /* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */ #define HPI_STATUS_ADDR 0xFFF4 @@ -664,9 +663,7 @@ static int go7007_usb_interface_reset(struct go7007 *go) if (usb->board->flags & GO7007_USB_EZUSB) { /* Reset buffer in EZ-USB */ -#ifdef GO7007_USB_DEBUG pr_debug("resetting EZ-USB buffers\n"); -#endif if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 || go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0) return -1; @@ -680,8 +677,7 @@ static int go7007_usb_interface_reset(struct go7007 *go) /* Wait for an interrupt to indicate successful hardware reset */ if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || (intr_val & ~0x1) != 0x55aa) { - printk(KERN_ERR - "go7007-usb: unable to reset the USB interface\n"); + pr_err("unable to reset the USB interface\n"); return -1; } return 0; @@ -695,9 +691,7 @@ static int go7007_usb_ezusb_write_interrupt(struct go7007 *go, u16 status_reg = 0; int timeout = 500; -#ifdef GO7007_USB_DEBUG pr_debug("WriteInterrupt: %04x %04x\n", addr, data); -#endif for (i = 0; i < 100; ++i) { r = usb_control_msg(usb->usbdev, @@ -715,9 +709,7 @@ static int go7007_usb_ezusb_write_interrupt(struct go7007 *go, if (r < 0) goto write_int_error; if (i == 100) { - printk(KERN_ERR - "go7007-usb: device is hung, status reg = 0x%04x\n", - status_reg); + pr_err("device is hung, status reg = 0x%04x\n", status_reg); return -1; } r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 0x12, @@ -733,7 +725,7 @@ static int go7007_usb_ezusb_write_interrupt(struct go7007 *go, return 0; write_int_error: - printk(KERN_ERR "go7007-usb: error in WriteInterrupt: %d\n", r); + pr_err("error in WriteInterrupt: %d\n", r); return r; } @@ -744,9 +736,7 @@ static int go7007_usb_onboard_write_interrupt(struct go7007 *go, int r; int timeout = 500; -#ifdef GO7007_USB_DEBUG pr_debug("WriteInterrupt: %04x %04x\n", addr, data); -#endif go->usb_buf[0] = data & 0xff; go->usb_buf[1] = data >> 8; @@ -757,7 +747,7 @@ static int go7007_usb_onboard_write_interrupt(struct go7007 *go, USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa, 0xf0f0, go->usb_buf, 8, timeout); if (r < 0) { - printk(KERN_ERR "go7007-usb: error in WriteInterrupt: %d\n", r); + pr_err("error in WriteInterrupt: %d\n", r); return r; } return 0; @@ -772,23 +762,19 @@ static void go7007_usb_readinterrupt_complete(struct urb *urb) if (status) { if (status != -ESHUTDOWN && go->status != STATUS_SHUTDOWN) { - printk(KERN_ERR - "go7007-usb: error in read interrupt: %d\n", - urb->status); + pr_err("error in read interrupt: %d\n", urb->status); } else { wake_up(&go->interrupt_waitq); return; } } else if (urb->actual_length != urb->transfer_buffer_length) { - printk(KERN_ERR "go7007-usb: short read in interrupt pipe!\n"); + pr_err("short read in interrupt pipe!\n"); } else { go->interrupt_available = 1; go->interrupt_data = __le16_to_cpu(regs[0]); go->interrupt_value = __le16_to_cpu(regs[1]); -#ifdef GO7007_USB_DEBUG pr_debug("ReadInterrupt: %04x %04x\n", go->interrupt_value, go->interrupt_data); -#endif } wake_up(&go->interrupt_waitq); @@ -801,8 +787,7 @@ static int go7007_usb_read_interrupt(struct go7007 *go) r = usb_submit_urb(usb->intr_urb, GFP_KERNEL); if (r < 0) { - printk(KERN_ERR - "go7007-usb: unable to submit interrupt urb: %d\n", r); + pr_err("unable to submit interrupt urb: %d\n", r); return r; } return 0; @@ -818,18 +803,17 @@ static void go7007_usb_read_video_pipe_complete(struct urb *urb) return; } if (status) { - printk(KERN_ERR "go7007-usb: error in video pipe: %d\n", - status); + pr_err("error in video pipe: %d\n", status); return; } if (urb->actual_length != urb->transfer_buffer_length) { - printk(KERN_ERR "go7007-usb: short read in video pipe!\n"); + pr_err("short read in video pipe!\n"); return; } go7007_parse_video_stream(go, urb->transfer_buffer, urb->actual_length); r = usb_submit_urb(urb, GFP_ATOMIC); if (r < 0) - printk(KERN_ERR "go7007-usb: error in video pipe: %d\n", r); + pr_err("error in video pipe: %d\n", r); } static void go7007_usb_read_audio_pipe_complete(struct urb *urb) @@ -840,19 +824,19 @@ static void go7007_usb_read_audio_pipe_complete(struct urb *urb) if (!vb2_is_streaming(&go->vidq)) return; if (status) { - printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n", + pr_err("error in audio pipe: %d\n", status); return; } if (urb->actual_length != urb->transfer_buffer_length) { - printk(KERN_ERR "go7007-usb: short read in audio pipe!\n"); + pr_err("short read in audio pipe!\n"); return; } if (go->audio_deliver != NULL) go->audio_deliver(go, urb->transfer_buffer, urb->actual_length); r = usb_submit_urb(urb, GFP_ATOMIC); if (r < 0) - printk(KERN_ERR "go7007-usb: error in audio pipe: %d\n", r); + pr_err("error in audio pipe: %d\n", r); } static int go7007_usb_stream_start(struct go7007 *go) @@ -863,8 +847,7 @@ static int go7007_usb_stream_start(struct go7007 *go) for (i = 0; i < 8; ++i) { r = usb_submit_urb(usb->video_urbs[i], GFP_KERNEL); if (r < 0) { - printk(KERN_ERR "go7007-usb: error submitting video " - "urb %d: %d\n", i, r); + pr_err("error submitting video urb %d: %d\n", i, r); goto video_submit_failed; } } @@ -874,8 +857,7 @@ static int go7007_usb_stream_start(struct go7007 *go) for (i = 0; i < 8; ++i) { r = usb_submit_urb(usb->audio_urbs[i], GFP_KERNEL); if (r < 0) { - printk(KERN_ERR "go7007-usb: error submitting audio " - "urb %d: %d\n", i, r); + pr_err("error submitting audio urb %d: %d\n", i, r); goto audio_submit_failed; } } @@ -911,9 +893,7 @@ static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len) int transferred, pipe; int timeout = 500; -#ifdef GO7007_USB_DEBUG pr_debug("DownloadBuffer sending %d bytes\n", len); -#endif if (usb->board->flags & GO7007_USB_EZUSB) pipe = usb_sndbulkpipe(usb->usbdev, 2); @@ -999,9 +979,8 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, !(msgs[i].flags & I2C_M_RD) && (msgs[i + 1].flags & I2C_M_RD)) { #ifdef GO7007_I2C_DEBUG - pr_debug("i2c write/read %d/%d " - "bytes on %02x\n", msgs[i].len, - msgs[i + 1].len, msgs[i].addr); + pr_debug("i2c write/read %d/%d bytes on %02x\n", + msgs[i].len, msgs[i + 1].len, msgs[i].addr); #endif buf[0] = 0x01; buf[1] = msgs[i].len + 1; @@ -1011,9 +990,8 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, buf[buf_len++] = msgs[++i].len; } else if (msgs[i].flags & I2C_M_RD) { #ifdef GO7007_I2C_DEBUG - pr_debug("i2c read %d " - "bytes on %02x\n", msgs[i].len, - msgs[i].addr); + pr_debug("i2c read %d bytes on %02x\n", + msgs[i].len, msgs[i].addr); #endif buf[0] = 0x01; buf[1] = 1; @@ -1022,9 +1000,8 @@ static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, buf_len = 4; } else { #ifdef GO7007_I2C_DEBUG - pr_debug("i2c write %d " - "bytes on %02x\n", msgs[i].len, - msgs[i].addr); + pr_debug("i2c write %d bytes on %02x\n", + msgs[i].len, msgs[i].addr); #endif buf[0] = 0x00; buf[1] = msgs[i].len + 1; @@ -1122,14 +1099,13 @@ static int go7007_usb_probe(struct usb_interface *intf, board = &board_px_tv402u; break; case GO7007_BOARDID_LIFEVIEW_LR192: - printk(KERN_ERR "go7007-usb: The Lifeview TV Walker Ultra " - "is not supported. Sorry!\n"); + pr_err("The Lifeview TV Walker Ultra is not supported. Sorry!\n"); return -ENODEV; name = "Lifeview TV Walker Ultra"; board = &board_lifeview_lr192; break; case GO7007_BOARDID_SENSORAY_2250: - printk(KERN_INFO "Sensoray 2250 found\n"); + pr_info("Sensoray 2250 found\n"); name = "Sensoray 2250/2251"; board = &board_sensoray_2250; break; @@ -1138,7 +1114,7 @@ static int go7007_usb_probe(struct usb_interface *intf, board = &board_ads_usbav_709; break; default: - printk(KERN_ERR "go7007-usb: unknown board ID %d!\n", + pr_err("unknown board ID %d!\n", (unsigned int)id->driver_info); return -ENODEV; } @@ -1197,8 +1173,7 @@ static int go7007_usb_probe(struct usb_interface *intf, go->i2c_adapter.dev.parent = go->dev; i2c_set_adapdata(&go->i2c_adapter, go); if (i2c_add_adapter(&go->i2c_adapter) < 0) { - printk(KERN_ERR - "go7007-usb: error: i2c_add_adapter failed\n"); + pr_err("error: i2c_add_adapter failed\n"); goto allocfail; } go->i2c_adapter_online = 1; @@ -1248,8 +1223,9 @@ static int go7007_usb_probe(struct usb_interface *intf, /* Probe the tuner model on the TV402U */ if (go->board_id == GO7007_BOARDID_PX_TV402U) { /* Board strapping indicates tuner model */ - if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3, 1) < 0) { - printk(KERN_ERR "go7007-usb: GPIO read failed!\n"); + if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3, + 1) < 0) { + pr_err("GPIO read failed!\n"); goto allocfail; } switch (go->usb_buf[0] >> 6) { @@ -1273,15 +1249,14 @@ static int go7007_usb_probe(struct usb_interface *intf, sizeof(go->name)); break; default: - pr_debug("unable to detect " - "tuner type!\n"); + pr_debug("unable to detect tuner type!\n"); break; } /* Configure tuner mode selection inputs connected * to the EZ-USB GPIO output pins */ if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0, NULL, 0, 0) < 0) { - printk(KERN_ERR "go7007-usb: GPIO write failed!\n"); + pr_err("GPIO write failed!\n"); goto allocfail; } } @@ -1290,11 +1265,7 @@ static int go7007_usb_probe(struct usb_interface *intf, * a USB1.1 port. There will be silent corruption of the stream. */ if ((board->flags & GO7007_USB_EZUSB) && usbdev->speed != USB_SPEED_HIGH) - printk(KERN_ERR "go7007-usb: *** WARNING *** This device " - "must be connected to a USB 2.0 port! " - "Attempting to capture video through a USB 1.1 " - "port will result in stream corruption, even " - "at low bitrates!\n"); + pr_err("*** WARNING *** This device must be connected to a USB 2.0 port! Attempting to capture video through a USB 1.1 port will result in stream corruption, even at low bitrates!\n"); /* Allocate the URBs and buffers for receiving the video stream */ if (board->flags & GO7007_USB_EZUSB) { diff --git a/drivers/staging/media/lirc/lirc_bt829.c b/drivers/staging/media/lirc/lirc_bt829.c index fa31ee7dd6a9..fbbdce4c119f 100644 --- a/drivers/staging/media/lirc/lirc_bt829.c +++ b/drivers/staging/media/lirc/lirc_bt829.c @@ -132,7 +132,7 @@ int init_module(void) atir_driver.minor = -1; atir_driver.code_length = 8; atir_driver.sample_rate = 10; - atir_driver.data = 0; + atir_driver.data = NULL; atir_driver.add_to_buf = atir_add_to_buf; atir_driver.set_use_inc = atir_set_use_inc; atir_driver.set_use_dec = atir_set_use_dec; @@ -159,7 +159,7 @@ void cleanup_module(void) static int atir_init_start(void) { pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400); - if (pci_addr_lin == 0) { + if (!pci_addr_lin) { pr_info("pci mem must be mapped\n"); return 0; } diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 8e95a57a8c4c..51dbc13e757f 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -28,9 +28,6 @@ /* * OOB area specification layout: Total 32 available free bytes. */ -#ifdef CONFIG_MTD_SPINAND_ONDIEECC -static int enable_hw_ecc; -static int enable_read_hw_ecc; static inline struct spinand_state *mtd_to_state(struct mtd_info *mtd) { @@ -41,6 +38,10 @@ static inline struct spinand_state *mtd_to_state(struct mtd_info *mtd) return state; } +#ifdef CONFIG_MTD_SPINAND_ONDIEECC +static int enable_hw_ecc; +static int enable_read_hw_ecc; + static struct nand_ecclayout spinand_oob_64 = { .eccbytes = 24, .eccpos = { @@ -939,23 +940,7 @@ static struct spi_driver spinand_driver = { .remove = spinand_remove, }; -/* - * Device driver registration - */ -static int __init spinand_init(void) -{ - return spi_register_driver(&spinand_driver); -} - -/* - * unregister Device driver. - */ -static void __exit spinand_exit(void) -{ - spi_unregister_driver(&spinand_driver); -} -module_init(spinand_init); -module_exit(spinand_exit); +module_spi_driver(spinand_driver); MODULE_DESCRIPTION("SPI NAND driver for Micron"); MODULE_AUTHOR("Henry Pan <[email protected]>, Kamlakant Patel <[email protected]>"); diff --git a/drivers/staging/netlogic/xlr_net.c b/drivers/staging/netlogic/xlr_net.c index 46eabd0e426a..235d2b1ec593 100644 --- a/drivers/staging/netlogic/xlr_net.c +++ b/drivers/staging/netlogic/xlr_net.c @@ -44,8 +44,8 @@ #include <linux/platform_device.h> #include <asm/mipsregs.h> - -/* fmn.h - For FMN credit configuration and registering fmn_handler. +/* + * fmn.h - For FMN credit configuration and registering fmn_handler. * FMN is communication mechanism that allows processing agents within * XLR/XLS to communicate each other. */ @@ -90,7 +90,8 @@ static inline struct sk_buff *mac_get_skb_back_ptr(void *addr) { struct sk_buff **back_ptr; - /* this function should be used only for newly allocated packets. + /* + * this function should be used only for newly allocated packets. * It assumes the first cacheline is for the back pointer related * book keeping info. */ @@ -102,7 +103,8 @@ static inline void mac_put_skb_back_ptr(struct sk_buff *skb) { struct sk_buff **back_ptr = (struct sk_buff **)skb->data; - /* this function should be used only for newly allocated packets. + /* + * this function should be used only for newly allocated packets. * It assumes the first cacheline is for the back pointer related * book keeping info. */ @@ -500,8 +502,10 @@ static void xlr_config_fifo_spill_area(struct xlr_net_priv *priv) sizeof(u64)); } -/* Configure PDE to Round-Robin distribution of packets to the - * available cpu */ +/* + * Configure PDE to Round-Robin distribution of packets to the + * available cpu + */ static void xlr_config_pde(struct xlr_net_priv *priv) { int i = 0; @@ -528,8 +532,10 @@ static void xlr_config_pde(struct xlr_net_priv *priv) ((bkt_map >> 32) & 0xffffffff)); } -/* Setup the Message ring credits, bucket size and other - * common configuration */ +/* + * Setup the Message ring credits, bucket size and other + * common configuration + */ static void xlr_config_common(struct xlr_net_priv *priv) { struct xlr_fmn_info *gmac = priv->nd->gmac_fmn_info; @@ -545,8 +551,10 @@ static void xlr_config_common(struct xlr_net_priv *priv) bucket_size[i]); } - /* Setting non-core Credit counter register - * Distributing Gmac's credit to CPU's*/ + /* + * Setting non-core Credit counter register + * Distributing Gmac's credit to CPU's + */ for (i = 0; i < 8; i++) { for (j = 0; j < 8; j++) xlr_nae_wreg(priv->base_addr, @@ -593,7 +601,8 @@ static void xlr_config_translate_table(struct xlr_net_priv *priv) c1 = 3; c2 = 0; for (i = 0; i < 64; i++) { - /* On use_bkt set the b0, b1 are used, else + /* + * On use_bkt set the b0, b1 are used, else * the 4 classes are used, here implemented * a logic to distribute the packets to the * buckets equally or based on the class @@ -736,7 +745,8 @@ static int xlr_mii_read(struct mii_bus *bus, int phy_addr, int regnum) return ret; } -/* XLR ports are RGMII. XLS ports are SGMII mostly except the port0, +/* + * XLR ports are RGMII. XLS ports are SGMII mostly except the port0, * which can be configured either SGMII or RGMII, considered SGMII * by default, if board setup to RGMII the port_type need to set * accordingly.Serdes and PCS layer need to configured for SGMII diff --git a/drivers/staging/octeon-usb/cvmx-usbnx-defs.h b/drivers/staging/octeon-usb/cvmx-usbnx-defs.h deleted file mode 100644 index e06aafa5726a..000000000000 --- a/drivers/staging/octeon-usb/cvmx-usbnx-defs.h +++ /dev/null @@ -1,885 +0,0 @@ -/***********************license start*************** - * Copyright (c) 2003-2010 Cavium Networks ([email protected]). All rights - * reserved. - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * 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. - - * * Neither the name of Cavium Networks nor the names of - * its contributors may be used to endorse or promote products - * derived from this software without specific prior written - * permission. - - * This Software, including technical data, may be subject to U.S. export - * control laws, including the U.S. Export Administration Act and its associated - * regulations, and may be subject to export or import regulations in other - * countries. - - * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" - * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR - * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO - * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION - * OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM - * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, - * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF - * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR - * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR - * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. - ***********************license end**************************************/ - - -/** - * cvmx-usbnx-defs.h - * - * Configuration and status register (CSR) type definitions for - * Octeon usbnx. - * - */ -#ifndef __CVMX_USBNX_TYPEDEFS_H__ -#define __CVMX_USBNX_TYPEDEFS_H__ - -#define CVMX_USBNXBID1(bid) (((bid) & 1) * 0x10000000ull) -#define CVMX_USBNXBID2(bid) (((bid) & 1) * 0x100000000000ull) - -#define CVMX_USBNXREG1(reg, bid) \ - (CVMX_ADD_IO_SEG(0x0001180068000000ull | reg) + CVMX_USBNXBID1(bid)) -#define CVMX_USBNXREG2(reg, bid) \ - (CVMX_ADD_IO_SEG(0x00016F0000000000ull | reg) + CVMX_USBNXBID2(bid)) - -#define CVMX_USBNX_CLK_CTL(bid) CVMX_USBNXREG1(0x10, bid) -#define CVMX_USBNX_DMA0_INB_CHN0(bid) CVMX_USBNXREG2(0x818, bid) -#define CVMX_USBNX_DMA0_OUTB_CHN0(bid) CVMX_USBNXREG2(0x858, bid) -#define CVMX_USBNX_USBP_CTL_STATUS(bid) CVMX_USBNXREG1(0x18, bid) - -/** - * cvmx_usbn#_clk_ctl - * - * USBN_CLK_CTL = USBN's Clock Control - * - * This register is used to control the frequency of the hclk and the - * hreset and phy_rst signals. - */ -union cvmx_usbnx_clk_ctl { - uint64_t u64; - /** - * struct cvmx_usbnx_clk_ctl_s - * @divide2: The 'hclk' used by the USB subsystem is derived - * from the eclk. - * Also see the field DIVIDE. DIVIDE2<1> must currently - * be zero because it is not implemented, so the maximum - * ratio of eclk/hclk is currently 16. - * The actual divide number for hclk is: - * (DIVIDE2 + 1) * (DIVIDE + 1) - * @hclk_rst: When this field is '0' the HCLK-DIVIDER used to - * generate the hclk in the USB Subsystem is held - * in reset. This bit must be set to '0' before - * changing the value os DIVIDE in this register. - * The reset to the HCLK_DIVIDERis also asserted - * when core reset is asserted. - * @p_x_on: Force USB-PHY on during suspend. - * '1' USB-PHY XO block is powered-down during - * suspend. - * '0' USB-PHY XO block is powered-up during - * suspend. - * The value of this field must be set while POR is - * active. - * @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to - * remain powered in Suspend Mode. - * '1' The USB-PHY XO Bias, Bandgap and PLL are - * powered down in suspend mode. - * The value of this field must be set while POR is - * active. - * @p_c_sel: Phy clock speed select. - * Selects the reference clock / crystal frequency. - * '11': Reserved - * '10': 48 MHz (reserved when a crystal is used) - * '01': 24 MHz (reserved when a crystal is used) - * '00': 12 MHz - * The value of this field must be set while POR is - * active. - * NOTE: if a crystal is used as a reference clock, - * this field must be set to 12 MHz. - * @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV. - * @sd_mode: Scaledown mode for the USBC. Control timing events - * in the USBC, for normal operation this must be '0'. - * @s_bist: Starts bist on the hclk memories, during the '0' - * to '1' transition. - * @por: Power On Reset for the PHY. - * Resets all the PHYS registers and state machines. - * @enable: When '1' allows the generation of the hclk. When - * '0' the hclk will not be generated. SEE DIVIDE - * field of this register. - * @prst: When this field is '0' the reset associated with - * the phy_clk functionality in the USB Subsystem is - * help in reset. This bit should not be set to '1' - * until the time it takes 6 clocks (hclk or phy_clk, - * whichever is slower) has passed. Under normal - * operation once this bit is set to '1' it should not - * be set to '0'. - * @hrst: When this field is '0' the reset associated with - * the hclk functioanlity in the USB Subsystem is - * held in reset.This bit should not be set to '1' - * until 12ms after phy_clk is stable. Under normal - * operation, once this bit is set to '1' it should - * not be set to '0'. - * @divide: The frequency of 'hclk' used by the USB subsystem - * is the eclk frequency divided by the value of - * (DIVIDE2 + 1) * (DIVIDE + 1), also see the field - * DIVIDE2 of this register. - * The hclk frequency should be less than 125Mhz. - * After writing a value to this field the SW should - * read the field for the value written. - * The ENABLE field of this register should not be set - * until AFTER this field is set and then read. - */ - struct cvmx_usbnx_clk_ctl_s { - uint64_t reserved_20_63 : 44; - uint64_t divide2 : 2; - uint64_t hclk_rst : 1; - uint64_t p_x_on : 1; - uint64_t reserved_14_15 : 2; - uint64_t p_com_on : 1; - uint64_t p_c_sel : 2; - uint64_t cdiv_byp : 1; - uint64_t sd_mode : 2; - uint64_t s_bist : 1; - uint64_t por : 1; - uint64_t enable : 1; - uint64_t prst : 1; - uint64_t hrst : 1; - uint64_t divide : 3; - } s; - /** - * struct cvmx_usbnx_clk_ctl_cn30xx - * @hclk_rst: When this field is '0' the HCLK-DIVIDER used to - * generate the hclk in the USB Subsystem is held - * in reset. This bit must be set to '0' before - * changing the value os DIVIDE in this register. - * The reset to the HCLK_DIVIDERis also asserted - * when core reset is asserted. - * @p_x_on: Force USB-PHY on during suspend. - * '1' USB-PHY XO block is powered-down during - * suspend. - * '0' USB-PHY XO block is powered-up during - * suspend. - * The value of this field must be set while POR is - * active. - * @p_rclk: Phy refrence clock enable. - * '1' The PHY PLL uses the XO block output as a - * reference. - * '0' Reserved. - * @p_xenbn: Phy external clock enable. - * '1' The XO block uses the clock from a crystal. - * '0' The XO block uses an external clock supplied - * on the XO pin. USB_XI should be tied to - * ground for this usage. - * @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to - * remain powered in Suspend Mode. - * '1' The USB-PHY XO Bias, Bandgap and PLL are - * powered down in suspend mode. - * The value of this field must be set while POR is - * active. - * @p_c_sel: Phy clock speed select. - * Selects the reference clock / crystal frequency. - * '11': Reserved - * '10': 48 MHz - * '01': 24 MHz - * '00': 12 MHz - * The value of this field must be set while POR is - * active. - * @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV. - * @sd_mode: Scaledown mode for the USBC. Control timing events - * in the USBC, for normal operation this must be '0'. - * @s_bist: Starts bist on the hclk memories, during the '0' - * to '1' transition. - * @por: Power On Reset for the PHY. - * Resets all the PHYS registers and state machines. - * @enable: When '1' allows the generation of the hclk. When - * '0' the hclk will not be generated. - * @prst: When this field is '0' the reset associated with - * the phy_clk functionality in the USB Subsystem is - * help in reset. This bit should not be set to '1' - * until the time it takes 6 clocks (hclk or phy_clk, - * whichever is slower) has passed. Under normal - * operation once this bit is set to '1' it should not - * be set to '0'. - * @hrst: When this field is '0' the reset associated with - * the hclk functioanlity in the USB Subsystem is - * held in reset.This bit should not be set to '1' - * until 12ms after phy_clk is stable. Under normal - * operation, once this bit is set to '1' it should - * not be set to '0'. - * @divide: The 'hclk' used by the USB subsystem is derived - * from the eclk. The eclk will be divided by the - * value of this field +1 to determine the hclk - * frequency. (Also see HRST of this register). - * The hclk frequency must be less than 125 MHz. - */ - struct cvmx_usbnx_clk_ctl_cn30xx { - uint64_t reserved_18_63 : 46; - uint64_t hclk_rst : 1; - uint64_t p_x_on : 1; - uint64_t p_rclk : 1; - uint64_t p_xenbn : 1; - uint64_t p_com_on : 1; - uint64_t p_c_sel : 2; - uint64_t cdiv_byp : 1; - uint64_t sd_mode : 2; - uint64_t s_bist : 1; - uint64_t por : 1; - uint64_t enable : 1; - uint64_t prst : 1; - uint64_t hrst : 1; - uint64_t divide : 3; - } cn30xx; - struct cvmx_usbnx_clk_ctl_cn30xx cn31xx; - /** - * struct cvmx_usbnx_clk_ctl_cn50xx - * @divide2: The 'hclk' used by the USB subsystem is derived - * from the eclk. - * Also see the field DIVIDE. DIVIDE2<1> must currently - * be zero because it is not implemented, so the maximum - * ratio of eclk/hclk is currently 16. - * The actual divide number for hclk is: - * (DIVIDE2 + 1) * (DIVIDE + 1) - * @hclk_rst: When this field is '0' the HCLK-DIVIDER used to - * generate the hclk in the USB Subsystem is held - * in reset. This bit must be set to '0' before - * changing the value os DIVIDE in this register. - * The reset to the HCLK_DIVIDERis also asserted - * when core reset is asserted. - * @p_rtype: PHY reference clock type - * '0' The USB-PHY uses a 12MHz crystal as a clock - * source at the USB_XO and USB_XI pins - * '1' Reserved - * '2' The USB_PHY uses 12/24/48MHz 2.5V board clock - * at the USB_XO pin. USB_XI should be tied to - * ground in this case. - * '3' Reserved - * (bit 14 was P_XENBN on 3xxx) - * (bit 15 was P_RCLK on 3xxx) - * @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to - * remain powered in Suspend Mode. - * '1' The USB-PHY XO Bias, Bandgap and PLL are - * powered down in suspend mode. - * The value of this field must be set while POR is - * active. - * @p_c_sel: Phy clock speed select. - * Selects the reference clock / crystal frequency. - * '11': Reserved - * '10': 48 MHz (reserved when a crystal is used) - * '01': 24 MHz (reserved when a crystal is used) - * '00': 12 MHz - * The value of this field must be set while POR is - * active. - * NOTE: if a crystal is used as a reference clock, - * this field must be set to 12 MHz. - * @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV. - * @sd_mode: Scaledown mode for the USBC. Control timing events - * in the USBC, for normal operation this must be '0'. - * @s_bist: Starts bist on the hclk memories, during the '0' - * to '1' transition. - * @por: Power On Reset for the PHY. - * Resets all the PHYS registers and state machines. - * @enable: When '1' allows the generation of the hclk. When - * '0' the hclk will not be generated. SEE DIVIDE - * field of this register. - * @prst: When this field is '0' the reset associated with - * the phy_clk functionality in the USB Subsystem is - * help in reset. This bit should not be set to '1' - * until the time it takes 6 clocks (hclk or phy_clk, - * whichever is slower) has passed. Under normal - * operation once this bit is set to '1' it should not - * be set to '0'. - * @hrst: When this field is '0' the reset associated with - * the hclk functioanlity in the USB Subsystem is - * held in reset.This bit should not be set to '1' - * until 12ms after phy_clk is stable. Under normal - * operation, once this bit is set to '1' it should - * not be set to '0'. - * @divide: The frequency of 'hclk' used by the USB subsystem - * is the eclk frequency divided by the value of - * (DIVIDE2 + 1) * (DIVIDE + 1), also see the field - * DIVIDE2 of this register. - * The hclk frequency should be less than 125Mhz. - * After writing a value to this field the SW should - * read the field for the value written. - * The ENABLE field of this register should not be set - * until AFTER this field is set and then read. - */ - struct cvmx_usbnx_clk_ctl_cn50xx { - uint64_t reserved_20_63 : 44; - uint64_t divide2 : 2; - uint64_t hclk_rst : 1; - uint64_t reserved_16_16 : 1; - uint64_t p_rtype : 2; - uint64_t p_com_on : 1; - uint64_t p_c_sel : 2; - uint64_t cdiv_byp : 1; - uint64_t sd_mode : 2; - uint64_t s_bist : 1; - uint64_t por : 1; - uint64_t enable : 1; - uint64_t prst : 1; - uint64_t hrst : 1; - uint64_t divide : 3; - } cn50xx; - struct cvmx_usbnx_clk_ctl_cn50xx cn52xx; - struct cvmx_usbnx_clk_ctl_cn50xx cn56xx; -}; - -/** - * cvmx_usbn#_usbp_ctl_status - * - * USBN_USBP_CTL_STATUS = USBP Control And Status Register - * - * Contains general control and status information for the USBN block. - */ -union cvmx_usbnx_usbp_ctl_status { - uint64_t u64; - /** - * struct cvmx_usbnx_usbp_ctl_status_s - * @txrisetune: HS Transmitter Rise/Fall Time Adjustment - * @txvreftune: HS DC Voltage Level Adjustment - * @txfslstune: FS/LS Source Impedence Adjustment - * @txhsxvtune: Transmitter High-Speed Crossover Adjustment - * @sqrxtune: Squelch Threshold Adjustment - * @compdistune: Disconnect Threshold Adjustment - * @otgtune: VBUS Valid Threshold Adjustment - * @otgdisable: OTG Block Disable - * @portreset: Per_Port Reset - * @drvvbus: Drive VBUS - * @lsbist: Low-Speed BIST Enable. - * @fsbist: Full-Speed BIST Enable. - * @hsbist: High-Speed BIST Enable. - * @bist_done: PHY Bist Done. - * Asserted at the end of the PHY BIST sequence. - * @bist_err: PHY Bist Error. - * Indicates an internal error was detected during - * the BIST sequence. - * @tdata_out: PHY Test Data Out. - * Presents either internaly generated signals or - * test register contents, based upon the value of - * test_data_out_sel. - * @siddq: Drives the USBP (USB-PHY) SIDDQ input. - * Normally should be set to zero. - * When customers have no intent to use USB PHY - * interface, they should: - * - still provide 3.3V to USB_VDD33, and - * - tie USB_REXT to 3.3V supply, and - * - set USBN*_USBP_CTL_STATUS[SIDDQ]=1 - * @txpreemphasistune: HS Transmitter Pre-Emphasis Enable - * @dma_bmode: When set to 1 the L2C DMA address will be updated - * with byte-counts between packets. When set to 0 - * the L2C DMA address is incremented to the next - * 4-byte aligned address after adding byte-count. - * @usbc_end: Bigendian input to the USB Core. This should be - * set to '0' for operation. - * @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP. - * @tclk: PHY Test Clock, used to load TDATA_IN to the USBP. - * @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY. - * This signal enables the pull-down resistance on - * the D+ line. '1' pull down-resistance is connected - * to D+/ '0' pull down resistance is not connected - * to D+. When an A/B device is acting as a host - * (downstream-facing port), dp_pulldown and - * dm_pulldown are enabled. This must not toggle - * during normal opeartion. - * @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY. - * This signal enables the pull-down resistance on - * the D- line. '1' pull down-resistance is connected - * to D-. '0' pull down resistance is not connected - * to D-. When an A/B device is acting as a host - * (downstream-facing port), dp_pulldown and - * dm_pulldown are enabled. This must not toggle - * during normal opeartion. - * @hst_mode: When '0' the USB is acting as HOST, when '1' - * USB is acting as device. This field needs to be - * set while the USB is in reset. - * @tuning: Transmitter Tuning for High-Speed Operation. - * Tunes the current supply and rise/fall output - * times for high-speed operation. - * [20:19] == 11: Current supply increased - * approximately 9% - * [20:19] == 10: Current supply increased - * approximately 4.5% - * [20:19] == 01: Design default. - * [20:19] == 00: Current supply decreased - * approximately 4.5% - * [22:21] == 11: Rise and fall times are increased. - * [22:21] == 10: Design default. - * [22:21] == 01: Rise and fall times are decreased. - * [22:21] == 00: Rise and fall times are decreased - * further as compared to the 01 setting. - * @tx_bs_enh: Transmit Bit Stuffing on [15:8]. - * Enables or disables bit stuffing on data[15:8] - * when bit-stuffing is enabled. - * @tx_bs_en: Transmit Bit Stuffing on [7:0]. - * Enables or disables bit stuffing on data[7:0] - * when bit-stuffing is enabled. - * @loop_enb: PHY Loopback Test Enable. - * '1': During data transmission the receive is - * enabled. - * '0': During data transmission the receive is - * disabled. - * Must be '0' for normal operation. - * @vtest_enb: Analog Test Pin Enable. - * '1' The PHY's analog_test pin is enabled for the - * input and output of applicable analog test signals. - * '0' THe analog_test pin is disabled. - * @bist_enb: Built-In Self Test Enable. - * Used to activate BIST in the PHY. - * @tdata_sel: Test Data Out Select. - * '1' test_data_out[3:0] (PHY) register contents - * are output. '0' internaly generated signals are - * output. - * @taddr_in: Mode Address for Test Interface. - * Specifies the register address for writing to or - * reading from the PHY test interface register. - * @tdata_in: Internal Testing Register Input Data and Select - * This is a test bus. Data is present on [3:0], - * and its corresponding select (enable) is present - * on bits [7:4]. - * @ate_reset: Reset input from automatic test equipment. - * This is a test signal. When the USB Core is - * powered up (not in Susned Mode), an automatic - * tester can use this to disable phy_clock and - * free_clk, then re-eanable them with an aligned - * phase. - * '1': The phy_clk and free_clk outputs are - * disabled. "0": The phy_clock and free_clk outputs - * are available within a specific period after the - * de-assertion. - */ - struct cvmx_usbnx_usbp_ctl_status_s { - uint64_t txrisetune : 1; - uint64_t txvreftune : 4; - uint64_t txfslstune : 4; - uint64_t txhsxvtune : 2; - uint64_t sqrxtune : 3; - uint64_t compdistune : 3; - uint64_t otgtune : 3; - uint64_t otgdisable : 1; - uint64_t portreset : 1; - uint64_t drvvbus : 1; - uint64_t lsbist : 1; - uint64_t fsbist : 1; - uint64_t hsbist : 1; - uint64_t bist_done : 1; - uint64_t bist_err : 1; - uint64_t tdata_out : 4; - uint64_t siddq : 1; - uint64_t txpreemphasistune : 1; - uint64_t dma_bmode : 1; - uint64_t usbc_end : 1; - uint64_t usbp_bist : 1; - uint64_t tclk : 1; - uint64_t dp_pulld : 1; - uint64_t dm_pulld : 1; - uint64_t hst_mode : 1; - uint64_t tuning : 4; - uint64_t tx_bs_enh : 1; - uint64_t tx_bs_en : 1; - uint64_t loop_enb : 1; - uint64_t vtest_enb : 1; - uint64_t bist_enb : 1; - uint64_t tdata_sel : 1; - uint64_t taddr_in : 4; - uint64_t tdata_in : 8; - uint64_t ate_reset : 1; - } s; - /** - * struct cvmx_usbnx_usbp_ctl_status_cn30xx - * @bist_done: PHY Bist Done. - * Asserted at the end of the PHY BIST sequence. - * @bist_err: PHY Bist Error. - * Indicates an internal error was detected during - * the BIST sequence. - * @tdata_out: PHY Test Data Out. - * Presents either internaly generated signals or - * test register contents, based upon the value of - * test_data_out_sel. - * @dma_bmode: When set to 1 the L2C DMA address will be updated - * with byte-counts between packets. When set to 0 - * the L2C DMA address is incremented to the next - * 4-byte aligned address after adding byte-count. - * @usbc_end: Bigendian input to the USB Core. This should be - * set to '0' for operation. - * @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP. - * @tclk: PHY Test Clock, used to load TDATA_IN to the USBP. - * @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY. - * This signal enables the pull-down resistance on - * the D+ line. '1' pull down-resistance is connected - * to D+/ '0' pull down resistance is not connected - * to D+. When an A/B device is acting as a host - * (downstream-facing port), dp_pulldown and - * dm_pulldown are enabled. This must not toggle - * during normal opeartion. - * @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY. - * This signal enables the pull-down resistance on - * the D- line. '1' pull down-resistance is connected - * to D-. '0' pull down resistance is not connected - * to D-. When an A/B device is acting as a host - * (downstream-facing port), dp_pulldown and - * dm_pulldown are enabled. This must not toggle - * during normal opeartion. - * @hst_mode: When '0' the USB is acting as HOST, when '1' - * USB is acting as device. This field needs to be - * set while the USB is in reset. - * @tuning: Transmitter Tuning for High-Speed Operation. - * Tunes the current supply and rise/fall output - * times for high-speed operation. - * [20:19] == 11: Current supply increased - * approximately 9% - * [20:19] == 10: Current supply increased - * approximately 4.5% - * [20:19] == 01: Design default. - * [20:19] == 00: Current supply decreased - * approximately 4.5% - * [22:21] == 11: Rise and fall times are increased. - * [22:21] == 10: Design default. - * [22:21] == 01: Rise and fall times are decreased. - * [22:21] == 00: Rise and fall times are decreased - * further as compared to the 01 setting. - * @tx_bs_enh: Transmit Bit Stuffing on [15:8]. - * Enables or disables bit stuffing on data[15:8] - * when bit-stuffing is enabled. - * @tx_bs_en: Transmit Bit Stuffing on [7:0]. - * Enables or disables bit stuffing on data[7:0] - * when bit-stuffing is enabled. - * @loop_enb: PHY Loopback Test Enable. - * '1': During data transmission the receive is - * enabled. - * '0': During data transmission the receive is - * disabled. - * Must be '0' for normal operation. - * @vtest_enb: Analog Test Pin Enable. - * '1' The PHY's analog_test pin is enabled for the - * input and output of applicable analog test signals. - * '0' THe analog_test pin is disabled. - * @bist_enb: Built-In Self Test Enable. - * Used to activate BIST in the PHY. - * @tdata_sel: Test Data Out Select. - * '1' test_data_out[3:0] (PHY) register contents - * are output. '0' internaly generated signals are - * output. - * @taddr_in: Mode Address for Test Interface. - * Specifies the register address for writing to or - * reading from the PHY test interface register. - * @tdata_in: Internal Testing Register Input Data and Select - * This is a test bus. Data is present on [3:0], - * and its corresponding select (enable) is present - * on bits [7:4]. - * @ate_reset: Reset input from automatic test equipment. - * This is a test signal. When the USB Core is - * powered up (not in Susned Mode), an automatic - * tester can use this to disable phy_clock and - * free_clk, then re-eanable them with an aligned - * phase. - * '1': The phy_clk and free_clk outputs are - * disabled. "0": The phy_clock and free_clk outputs - * are available within a specific period after the - * de-assertion. - */ - struct cvmx_usbnx_usbp_ctl_status_cn30xx { - uint64_t reserved_38_63 : 26; - uint64_t bist_done : 1; - uint64_t bist_err : 1; - uint64_t tdata_out : 4; - uint64_t reserved_30_31 : 2; - uint64_t dma_bmode : 1; - uint64_t usbc_end : 1; - uint64_t usbp_bist : 1; - uint64_t tclk : 1; - uint64_t dp_pulld : 1; - uint64_t dm_pulld : 1; - uint64_t hst_mode : 1; - uint64_t tuning : 4; - uint64_t tx_bs_enh : 1; - uint64_t tx_bs_en : 1; - uint64_t loop_enb : 1; - uint64_t vtest_enb : 1; - uint64_t bist_enb : 1; - uint64_t tdata_sel : 1; - uint64_t taddr_in : 4; - uint64_t tdata_in : 8; - uint64_t ate_reset : 1; - } cn30xx; - /** - * struct cvmx_usbnx_usbp_ctl_status_cn50xx - * @txrisetune: HS Transmitter Rise/Fall Time Adjustment - * @txvreftune: HS DC Voltage Level Adjustment - * @txfslstune: FS/LS Source Impedence Adjustment - * @txhsxvtune: Transmitter High-Speed Crossover Adjustment - * @sqrxtune: Squelch Threshold Adjustment - * @compdistune: Disconnect Threshold Adjustment - * @otgtune: VBUS Valid Threshold Adjustment - * @otgdisable: OTG Block Disable - * @portreset: Per_Port Reset - * @drvvbus: Drive VBUS - * @lsbist: Low-Speed BIST Enable. - * @fsbist: Full-Speed BIST Enable. - * @hsbist: High-Speed BIST Enable. - * @bist_done: PHY Bist Done. - * Asserted at the end of the PHY BIST sequence. - * @bist_err: PHY Bist Error. - * Indicates an internal error was detected during - * the BIST sequence. - * @tdata_out: PHY Test Data Out. - * Presents either internaly generated signals or - * test register contents, based upon the value of - * test_data_out_sel. - * @txpreemphasistune: HS Transmitter Pre-Emphasis Enable - * @dma_bmode: When set to 1 the L2C DMA address will be updated - * with byte-counts between packets. When set to 0 - * the L2C DMA address is incremented to the next - * 4-byte aligned address after adding byte-count. - * @usbc_end: Bigendian input to the USB Core. This should be - * set to '0' for operation. - * @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP. - * @tclk: PHY Test Clock, used to load TDATA_IN to the USBP. - * @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY. - * This signal enables the pull-down resistance on - * the D+ line. '1' pull down-resistance is connected - * to D+/ '0' pull down resistance is not connected - * to D+. When an A/B device is acting as a host - * (downstream-facing port), dp_pulldown and - * dm_pulldown are enabled. This must not toggle - * during normal opeartion. - * @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY. - * This signal enables the pull-down resistance on - * the D- line. '1' pull down-resistance is connected - * to D-. '0' pull down resistance is not connected - * to D-. When an A/B device is acting as a host - * (downstream-facing port), dp_pulldown and - * dm_pulldown are enabled. This must not toggle - * during normal opeartion. - * @hst_mode: When '0' the USB is acting as HOST, when '1' - * USB is acting as device. This field needs to be - * set while the USB is in reset. - * @tx_bs_enh: Transmit Bit Stuffing on [15:8]. - * Enables or disables bit stuffing on data[15:8] - * when bit-stuffing is enabled. - * @tx_bs_en: Transmit Bit Stuffing on [7:0]. - * Enables or disables bit stuffing on data[7:0] - * when bit-stuffing is enabled. - * @loop_enb: PHY Loopback Test Enable. - * '1': During data transmission the receive is - * enabled. - * '0': During data transmission the receive is - * disabled. - * Must be '0' for normal operation. - * @vtest_enb: Analog Test Pin Enable. - * '1' The PHY's analog_test pin is enabled for the - * input and output of applicable analog test signals. - * '0' THe analog_test pin is disabled. - * @bist_enb: Built-In Self Test Enable. - * Used to activate BIST in the PHY. - * @tdata_sel: Test Data Out Select. - * '1' test_data_out[3:0] (PHY) register contents - * are output. '0' internaly generated signals are - * output. - * @taddr_in: Mode Address for Test Interface. - * Specifies the register address for writing to or - * reading from the PHY test interface register. - * @tdata_in: Internal Testing Register Input Data and Select - * This is a test bus. Data is present on [3:0], - * and its corresponding select (enable) is present - * on bits [7:4]. - * @ate_reset: Reset input from automatic test equipment. - * This is a test signal. When the USB Core is - * powered up (not in Susned Mode), an automatic - * tester can use this to disable phy_clock and - * free_clk, then re-eanable them with an aligned - * phase. - * '1': The phy_clk and free_clk outputs are - * disabled. "0": The phy_clock and free_clk outputs - * are available within a specific period after the - * de-assertion. - */ - struct cvmx_usbnx_usbp_ctl_status_cn50xx { - uint64_t txrisetune : 1; - uint64_t txvreftune : 4; - uint64_t txfslstune : 4; - uint64_t txhsxvtune : 2; - uint64_t sqrxtune : 3; - uint64_t compdistune : 3; - uint64_t otgtune : 3; - uint64_t otgdisable : 1; - uint64_t portreset : 1; - uint64_t drvvbus : 1; - uint64_t lsbist : 1; - uint64_t fsbist : 1; - uint64_t hsbist : 1; - uint64_t bist_done : 1; - uint64_t bist_err : 1; - uint64_t tdata_out : 4; - uint64_t reserved_31_31 : 1; - uint64_t txpreemphasistune : 1; - uint64_t dma_bmode : 1; - uint64_t usbc_end : 1; - uint64_t usbp_bist : 1; - uint64_t tclk : 1; - uint64_t dp_pulld : 1; - uint64_t dm_pulld : 1; - uint64_t hst_mode : 1; - uint64_t reserved_19_22 : 4; - uint64_t tx_bs_enh : 1; - uint64_t tx_bs_en : 1; - uint64_t loop_enb : 1; - uint64_t vtest_enb : 1; - uint64_t bist_enb : 1; - uint64_t tdata_sel : 1; - uint64_t taddr_in : 4; - uint64_t tdata_in : 8; - uint64_t ate_reset : 1; - } cn50xx; - /** - * struct cvmx_usbnx_usbp_ctl_status_cn52xx - * @txrisetune: HS Transmitter Rise/Fall Time Adjustment - * @txvreftune: HS DC Voltage Level Adjustment - * @txfslstune: FS/LS Source Impedence Adjustment - * @txhsxvtune: Transmitter High-Speed Crossover Adjustment - * @sqrxtune: Squelch Threshold Adjustment - * @compdistune: Disconnect Threshold Adjustment - * @otgtune: VBUS Valid Threshold Adjustment - * @otgdisable: OTG Block Disable - * @portreset: Per_Port Reset - * @drvvbus: Drive VBUS - * @lsbist: Low-Speed BIST Enable. - * @fsbist: Full-Speed BIST Enable. - * @hsbist: High-Speed BIST Enable. - * @bist_done: PHY Bist Done. - * Asserted at the end of the PHY BIST sequence. - * @bist_err: PHY Bist Error. - * Indicates an internal error was detected during - * the BIST sequence. - * @tdata_out: PHY Test Data Out. - * Presents either internaly generated signals or - * test register contents, based upon the value of - * test_data_out_sel. - * @siddq: Drives the USBP (USB-PHY) SIDDQ input. - * Normally should be set to zero. - * When customers have no intent to use USB PHY - * interface, they should: - * - still provide 3.3V to USB_VDD33, and - * - tie USB_REXT to 3.3V supply, and - * - set USBN*_USBP_CTL_STATUS[SIDDQ]=1 - * @txpreemphasistune: HS Transmitter Pre-Emphasis Enable - * @dma_bmode: When set to 1 the L2C DMA address will be updated - * with byte-counts between packets. When set to 0 - * the L2C DMA address is incremented to the next - * 4-byte aligned address after adding byte-count. - * @usbc_end: Bigendian input to the USB Core. This should be - * set to '0' for operation. - * @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP. - * @tclk: PHY Test Clock, used to load TDATA_IN to the USBP. - * @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY. - * This signal enables the pull-down resistance on - * the D+ line. '1' pull down-resistance is connected - * to D+/ '0' pull down resistance is not connected - * to D+. When an A/B device is acting as a host - * (downstream-facing port), dp_pulldown and - * dm_pulldown are enabled. This must not toggle - * during normal opeartion. - * @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY. - * This signal enables the pull-down resistance on - * the D- line. '1' pull down-resistance is connected - * to D-. '0' pull down resistance is not connected - * to D-. When an A/B device is acting as a host - * (downstream-facing port), dp_pulldown and - * dm_pulldown are enabled. This must not toggle - * during normal opeartion. - * @hst_mode: When '0' the USB is acting as HOST, when '1' - * USB is acting as device. This field needs to be - * set while the USB is in reset. - * @tx_bs_enh: Transmit Bit Stuffing on [15:8]. - * Enables or disables bit stuffing on data[15:8] - * when bit-stuffing is enabled. - * @tx_bs_en: Transmit Bit Stuffing on [7:0]. - * Enables or disables bit stuffing on data[7:0] - * when bit-stuffing is enabled. - * @loop_enb: PHY Loopback Test Enable. - * '1': During data transmission the receive is - * enabled. - * '0': During data transmission the receive is - * disabled. - * Must be '0' for normal operation. - * @vtest_enb: Analog Test Pin Enable. - * '1' The PHY's analog_test pin is enabled for the - * input and output of applicable analog test signals. - * '0' THe analog_test pin is disabled. - * @bist_enb: Built-In Self Test Enable. - * Used to activate BIST in the PHY. - * @tdata_sel: Test Data Out Select. - * '1' test_data_out[3:0] (PHY) register contents - * are output. '0' internaly generated signals are - * output. - * @taddr_in: Mode Address for Test Interface. - * Specifies the register address for writing to or - * reading from the PHY test interface register. - * @tdata_in: Internal Testing Register Input Data and Select - * This is a test bus. Data is present on [3:0], - * and its corresponding select (enable) is present - * on bits [7:4]. - * @ate_reset: Reset input from automatic test equipment. - * This is a test signal. When the USB Core is - * powered up (not in Susned Mode), an automatic - * tester can use this to disable phy_clock and - * free_clk, then re-eanable them with an aligned - * phase. - * '1': The phy_clk and free_clk outputs are - * disabled. "0": The phy_clock and free_clk outputs - * are available within a specific period after the - * de-assertion. - */ - struct cvmx_usbnx_usbp_ctl_status_cn52xx { - uint64_t txrisetune : 1; - uint64_t txvreftune : 4; - uint64_t txfslstune : 4; - uint64_t txhsxvtune : 2; - uint64_t sqrxtune : 3; - uint64_t compdistune : 3; - uint64_t otgtune : 3; - uint64_t otgdisable : 1; - uint64_t portreset : 1; - uint64_t drvvbus : 1; - uint64_t lsbist : 1; - uint64_t fsbist : 1; - uint64_t hsbist : 1; - uint64_t bist_done : 1; - uint64_t bist_err : 1; - uint64_t tdata_out : 4; - uint64_t siddq : 1; - uint64_t txpreemphasistune : 1; - uint64_t dma_bmode : 1; - uint64_t usbc_end : 1; - uint64_t usbp_bist : 1; - uint64_t tclk : 1; - uint64_t dp_pulld : 1; - uint64_t dm_pulld : 1; - uint64_t hst_mode : 1; - uint64_t reserved_19_22 : 4; - uint64_t tx_bs_enh : 1; - uint64_t tx_bs_en : 1; - uint64_t loop_enb : 1; - uint64_t vtest_enb : 1; - uint64_t bist_enb : 1; - uint64_t tdata_sel : 1; - uint64_t taddr_in : 4; - uint64_t tdata_in : 8; - uint64_t ate_reset : 1; - } cn52xx; -}; - -#endif diff --git a/drivers/staging/octeon-usb/octeon-hcd.c b/drivers/staging/octeon-usb/octeon-hcd.c index 1859c050b918..d118952c0a74 100644 --- a/drivers/staging/octeon-usb/octeon-hcd.c +++ b/drivers/staging/octeon-usb/octeon-hcd.c @@ -66,8 +66,7 @@ #include <asm/octeon/cvmx-sysinfo.h> #include <asm/octeon/cvmx-helper-board.h> -#include "cvmx-usbcx-defs.h" -#include "cvmx-usbnx-defs.h" +#include "octeon-hcd.h" /** * enum cvmx_usb_speed - the possible USB device speeds @@ -235,8 +234,6 @@ enum cvmx_usb_initialize_flags { /** * enum cvmx_usb_pipe_flags - internal flags for a pipe. * - * @__CVMX_USB_PIPE_FLAGS_OPEN: Used internally to determine if a pipe is - * open. Do not use. * @__CVMX_USB_PIPE_FLAGS_SCHEDULED: Used internally to determine if a pipe is * actively using hardware. Do not use. * @__CVMX_USB_PIPE_FLAGS_NEED_PING: Used internally to determine if a high @@ -244,7 +241,6 @@ enum cvmx_usb_initialize_flags { * use. */ enum cvmx_usb_pipe_flags { - __CVMX_USB_PIPE_FLAGS_OPEN = 1 << 16, __CVMX_USB_PIPE_FLAGS_SCHEDULED = 1 << 17, __CVMX_USB_PIPE_FLAGS_NEED_PING = 1 << 18, }; @@ -255,12 +251,6 @@ enum cvmx_usb_pipe_flags { /* Maximum number of times to retry failed transactions */ #define MAX_RETRIES 3 -/* Maximum number of pipes that can be open at once */ -#define MAX_PIPES 32 - -/* Maximum number of outstanding transactions across all pipes */ -#define MAX_TRANSACTIONS 256 - /* Maximum number of hardware channels supported by the USB block */ #define MAX_CHANNELS 8 @@ -285,10 +275,6 @@ enum cvmx_usb_pipe_flags { */ #define MAX_TRANSFER_PACKETS ((1<<10)-1) -enum cvmx_usb_transaction_flags { - __CVMX_USB_TRANSACTION_FLAGS_IN_USE = 1<<16, -}; - enum { USB_CLOCK_TYPE_REF_12, USB_CLOCK_TYPE_REF_24, @@ -320,8 +306,7 @@ enum cvmx_usb_stage { * regardless of type. These are linked together * to form a list of pending requests for a pipe. * - * @prev: Transaction before this one in the pipe. - * @next: Transaction after this one in the pipe. + * @node: List node for transactions in the pipe. * @type: Type of transaction, duplicated of the pipe. * @flags: State flags for this transaction. * @buffer: User's physical buffer address to read/write. @@ -337,10 +322,8 @@ enum cvmx_usb_stage { * @urb: URB. */ struct cvmx_usb_transaction { - struct cvmx_usb_transaction *prev; - struct cvmx_usb_transaction *next; + struct list_head node; enum cvmx_usb_transfer type; - enum cvmx_usb_transaction_flags flags; uint64_t buffer; int buffer_length; uint64_t control_header; @@ -360,10 +343,9 @@ struct cvmx_usb_transaction { * and some USB device. It contains a list of pending * request to the device. * - * @prev: Pipe before this one in the list + * @node: List node for pipe list * @next: Pipe after this one in the list - * @head: The first pending transaction - * @tail: The last pending transaction + * @transactions: List of pending transactions * @interval: For periodic pipes, the interval between packets in * frames * @next_tx_frame: The next frame this pipe is allowed to transmit on @@ -384,10 +366,8 @@ struct cvmx_usb_transaction { * complete should be sent on */ struct cvmx_usb_pipe { - struct cvmx_usb_pipe *prev; - struct cvmx_usb_pipe *next; - struct cvmx_usb_transaction *head; - struct cvmx_usb_transaction *tail; + struct list_head node; + struct list_head transactions; uint64_t interval; uint64_t next_tx_frame; enum cvmx_usb_pipe_flags flags; @@ -405,17 +385,6 @@ struct cvmx_usb_pipe { int8_t split_sc_frame; }; -/** - * struct cvmx_usb_pipe_list - * - * @head: Head of the list, or NULL if empty. - * @tail: Tail if the list, or NULL if empty. - */ -struct cvmx_usb_pipe_list { - struct cvmx_usb_pipe *head; - struct cvmx_usb_pipe *tail; -}; - struct cvmx_usb_tx_fifo { struct { int channel; @@ -435,13 +404,9 @@ struct cvmx_usb_tx_fifo { * usbcx_hprt: Stored port status so we don't need to read a CSR to * determine splits. * pipe_for_channel: Map channels to pipes. - * free_transaction_head: List of free transactions head. - * free_transaction_tail: List of free transactions tail. * pipe: Storage for pipes. - * transaction: Storage for transactions. * indent: Used by debug output to indent functions. * port_status: Last port status used for change notification. - * free_pipes: List of all pipes that are currently closed. * idle_pipes: List of open pipes that have no transactions. * active_pipes: Active pipes indexed by transfer type. * frame_number: Increments every SOF interrupt for time keeping. @@ -453,15 +418,10 @@ struct cvmx_usb_state { int idle_hardware_channels; union cvmx_usbcx_hprt usbcx_hprt; struct cvmx_usb_pipe *pipe_for_channel[MAX_CHANNELS]; - struct cvmx_usb_transaction *free_transaction_head; - struct cvmx_usb_transaction *free_transaction_tail; - struct cvmx_usb_pipe pipe[MAX_PIPES]; - struct cvmx_usb_transaction transaction[MAX_TRANSACTIONS]; int indent; struct cvmx_usb_port_status port_status; - struct cvmx_usb_pipe_list free_pipes; - struct cvmx_usb_pipe_list idle_pipes; - struct cvmx_usb_pipe_list active_pipes[4]; + struct list_head idle_pipes; + struct list_head active_pipes[4]; uint64_t frame_number; struct cvmx_usb_transaction *active_split; struct cvmx_usb_tx_fifo periodic; @@ -653,98 +613,6 @@ static int cvmx_usb_get_num_ports(void) return arch_ports; } - -/** - * Allocate a usb transaction for use - * - * @usb: USB device state populated by - * cvmx_usb_initialize(). - * - * Returns: Transaction or NULL - */ -static inline struct cvmx_usb_transaction *__cvmx_usb_alloc_transaction(struct cvmx_usb_state *usb) -{ - struct cvmx_usb_transaction *t; - t = usb->free_transaction_head; - if (t) { - usb->free_transaction_head = t->next; - if (!usb->free_transaction_head) - usb->free_transaction_tail = NULL; - } - if (t) { - memset(t, 0, sizeof(*t)); - t->flags = __CVMX_USB_TRANSACTION_FLAGS_IN_USE; - } - return t; -} - - -/** - * Free a usb transaction - * - * @usb: USB device state populated by - * cvmx_usb_initialize(). - * @transaction: - * Transaction to free - */ -static inline void __cvmx_usb_free_transaction(struct cvmx_usb_state *usb, - struct cvmx_usb_transaction *transaction) -{ - transaction->flags = 0; - transaction->prev = NULL; - transaction->next = NULL; - if (usb->free_transaction_tail) - usb->free_transaction_tail->next = transaction; - else - usb->free_transaction_head = transaction; - usb->free_transaction_tail = transaction; -} - - -/** - * Add a pipe to the tail of a list - * @list: List to add pipe to - * @pipe: Pipe to add - */ -static inline void __cvmx_usb_append_pipe(struct cvmx_usb_pipe_list *list, struct cvmx_usb_pipe *pipe) -{ - pipe->next = NULL; - pipe->prev = list->tail; - if (list->tail) - list->tail->next = pipe; - else - list->head = pipe; - list->tail = pipe; -} - - -/** - * Remove a pipe from a list - * @list: List to remove pipe from - * @pipe: Pipe to remove - */ -static inline void __cvmx_usb_remove_pipe(struct cvmx_usb_pipe_list *list, struct cvmx_usb_pipe *pipe) -{ - if (list->head == pipe) { - list->head = pipe->next; - pipe->next = NULL; - if (list->head) - list->head->prev = NULL; - else - list->tail = NULL; - } else if (list->tail == pipe) { - list->tail = pipe->prev; - list->tail->next = NULL; - pipe->prev = NULL; - } else { - pipe->prev->next = pipe->next; - pipe->next->prev = pipe->prev; - pipe->prev = NULL; - pipe->next = NULL; - } -} - - /** * Initialize a USB port for use. This must be called before any * other access to the Octeon USB port is made. The port starts @@ -765,6 +633,7 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb, union cvmx_usbnx_clk_ctl usbn_clk_ctl; union cvmx_usbnx_usbp_ctl_status usbn_usbp_ctl_status; enum cvmx_usb_initialize_flags flags = 0; + int i; /* At first allow 0-1 for the usb port number */ if ((usb_port_number < 0) || (usb_port_number > 1)) @@ -799,18 +668,10 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb, usb->init_flags = flags; /* Initialize the USB state structure */ - { - int i; - usb->index = usb_port_number; - - /* Initialize the transaction double linked list */ - usb->free_transaction_head = NULL; - usb->free_transaction_tail = NULL; - for (i = 0; i < MAX_TRANSACTIONS; i++) - __cvmx_usb_free_transaction(usb, usb->transaction + i); - for (i = 0; i < MAX_PIPES; i++) - __cvmx_usb_append_pipe(&usb->free_pipes, usb->pipe + i); - } + usb->index = usb_port_number; + INIT_LIST_HEAD(&usb->idle_pipes); + for (i = 0; i < ARRAY_SIZE(usb->active_pipes); i++) + INIT_LIST_HEAD(&usb->active_pipes[i]); /* * Power On Reset and PHY Initialization @@ -836,16 +697,14 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb, * source at USB_XO. USB_XI should be tied to GND. * Most Octeon evaluation boards require this setting */ - if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { - /* From CN31XX,CN30XX manual */ - usbn_clk_ctl.cn31xx.p_rclk = 1; - usbn_clk_ctl.cn31xx.p_xenbn = 0; - } else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) - /* From CN56XX,CN50XX manual */ - usbn_clk_ctl.cn56xx.p_rtype = 2; + if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || + OCTEON_IS_MODEL(OCTEON_CN56XX) || + OCTEON_IS_MODEL(OCTEON_CN50XX)) + /* From CN56XX,CN50XX,CN31XX,CN30XX manuals */ + usbn_clk_ctl.s.p_rtype = 2; /* p_rclk=1 & p_xenbn=0 */ else /* From CN52XX manual */ - usbn_clk_ctl.cn52xx.p_rtype = 1; + usbn_clk_ctl.s.p_rtype = 1; switch (flags & CVMX_USB_INITIALIZE_FLAGS_CLOCK_MHZ_MASK) { case CVMX_USB_INITIALIZE_FLAGS_CLOCK_12MHZ: @@ -863,16 +722,12 @@ static int cvmx_usb_initialize(struct cvmx_usb_state *usb, * The USB port uses a 12MHz crystal as clock source * at USB_XO and USB_XI */ - if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) { + if (OCTEON_IS_MODEL(OCTEON_CN3XXX)) /* From CN31XX,CN30XX manual */ - usbn_clk_ctl.cn31xx.p_rclk = 1; - usbn_clk_ctl.cn31xx.p_xenbn = 1; - } else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) - /* From CN56XX,CN50XX manual */ - usbn_clk_ctl.cn56xx.p_rtype = 0; + usbn_clk_ctl.s.p_rtype = 3; /* p_rclk=1 & p_xenbn=1 */ else - /* From CN52XX manual */ - usbn_clk_ctl.cn52xx.p_rtype = 0; + /* From CN56XX,CN52XX,CN50XX manuals. */ + usbn_clk_ctl.s.p_rtype = 0; usbn_clk_ctl.s.p_c_sel = 0; } @@ -1092,11 +947,11 @@ static int cvmx_usb_shutdown(struct cvmx_usb_state *usb) union cvmx_usbnx_clk_ctl usbn_clk_ctl; /* Make sure all pipes are closed */ - if (usb->idle_pipes.head || - usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS].head || - usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT].head || - usb->active_pipes[CVMX_USB_TRANSFER_CONTROL].head || - usb->active_pipes[CVMX_USB_TRANSFER_BULK].head) + if (!list_empty(&usb->idle_pipes) || + !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_ISOCHRONOUS]) || + !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_INTERRUPT]) || + !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_CONTROL]) || + !list_empty(&usb->active_pipes[CVMX_USB_TRANSFER_BULK])) return -EBUSY; /* Disable the clocks and put them in power on reset */ @@ -1347,12 +1202,9 @@ static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb, if (unlikely((hub_port < 0) || (hub_port > MAX_USB_HUB_PORT))) return NULL; - /* Find a free pipe */ - pipe = usb->free_pipes.head; + pipe = kzalloc(sizeof(*pipe), GFP_ATOMIC); if (!pipe) return NULL; - __cvmx_usb_remove_pipe(&usb->free_pipes, pipe); - pipe->flags = __CVMX_USB_PIPE_FLAGS_OPEN; if ((device_speed == CVMX_USB_SPEED_HIGH) && (transfer_dir == CVMX_USB_DIRECTION_OUT) && (transfer_type == CVMX_USB_TRANSFER_BULK)) @@ -1363,6 +1215,8 @@ static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb, pipe->max_packet = max_packet; pipe->transfer_type = transfer_type; pipe->transfer_dir = transfer_dir; + INIT_LIST_HEAD(&pipe->transactions); + /* * All pipes use interval to rate limit NAK processing. Force an * interval if one wasn't supplied @@ -1382,7 +1236,7 @@ static struct cvmx_usb_pipe *cvmx_usb_open_pipe(struct cvmx_usb_state *usb, pipe->hub_port = hub_port; pipe->pid_toggle = 0; pipe->split_sc_frame = -1; - __cvmx_usb_append_pipe(&usb->idle_pipes, pipe); + list_add_tail(&pipe->node, &usb->idle_pipes); /* * We don't need to tell the hardware about this pipe yet since @@ -1588,7 +1442,9 @@ static void __cvmx_usb_start_channel_control(struct cvmx_usb_state *usb, int channel, struct cvmx_usb_pipe *pipe) { - struct cvmx_usb_transaction *transaction = pipe->head; + struct cvmx_usb_transaction *transaction = + list_first_entry(&pipe->transactions, typeof(*transaction), + node); union cvmx_usb_control_header *header = cvmx_phys_to_ptr(transaction->control_header); int bytes_to_transfer = transaction->buffer_length - transaction->actual_bytes; @@ -1717,7 +1573,9 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb, int channel, struct cvmx_usb_pipe *pipe) { - struct cvmx_usb_transaction *transaction = pipe->head; + struct cvmx_usb_transaction *transaction = + list_first_entry(&pipe->transactions, typeof(*transaction), + node); /* Make sure all writes to the DMA region get flushed */ CVMX_SYNCW; @@ -2011,19 +1869,21 @@ static void __cvmx_usb_start_channel(struct cvmx_usb_state *usb, * * Returns: Pipe or NULL if none are ready */ -static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(struct cvmx_usb_state *usb, struct cvmx_usb_pipe_list *list, uint64_t current_frame) +static struct cvmx_usb_pipe *__cvmx_usb_find_ready_pipe(struct cvmx_usb_state *usb, struct list_head *list, uint64_t current_frame) { - struct cvmx_usb_pipe *pipe = list->head; - while (pipe) { - if (!(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED) && pipe->head && + struct cvmx_usb_pipe *pipe; + + list_for_each_entry(pipe, list, node) { + struct cvmx_usb_transaction *t = + list_first_entry(&pipe->transactions, typeof(*t), node); + if (!(pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED) && t && (pipe->next_tx_frame <= current_frame) && ((pipe->split_sc_frame == -1) || ((((int)current_frame - (int)pipe->split_sc_frame) & 0x7f) < 0x40)) && - (!usb->active_split || (usb->active_split == pipe->head))) { + (!usb->active_split || (usb->active_split == t))) { CVMX_PREFETCH(pipe, 128); - CVMX_PREFETCH(pipe->head, 0); + CVMX_PREFETCH(t, 0); return pipe; } - pipe = pipe->next; } return NULL; } @@ -2090,13 +1950,11 @@ done: */ need_sof = 0; for (ttype = CVMX_USB_TRANSFER_CONTROL; ttype <= CVMX_USB_TRANSFER_INTERRUPT; ttype++) { - pipe = usb->active_pipes[ttype].head; - while (pipe) { + list_for_each_entry(pipe, &usb->active_pipes[ttype], node) { if (pipe->next_tx_frame > usb->frame_number) { need_sof = 1; break; } - pipe = pipe->next; } } USB_SET_FIELD32(CVMX_USBCX_GINTMSK(usb->index), union cvmx_usbcx_gintmsk, sofmsk, need_sof); @@ -2128,17 +1986,14 @@ static void octeon_usb_urb_complete_callback(struct cvmx_usb_state *usb, urb->actual_length = bytes_transferred; urb->hcpriv = NULL; - if (!list_empty(&urb->urb_list)) { + if (!list_empty(&urb->urb_list)) /* * It is on the dequeue_list, but we are going to call * usb_hcd_giveback_urb(), so we must clear it from * the list. We got to it before the * octeon_usb_urb_dequeue_work() tasklet did. */ - list_del(&urb->urb_list); - /* No longer on the dequeue_list. */ - INIT_LIST_HEAD(&urb->urb_list); - } + list_del_init(&urb->urb_list); /* For Isochronous transactions we need to update the URB packet status list from data in our private copy */ @@ -2253,24 +2108,14 @@ static void __cvmx_usb_perform_complete(struct cvmx_usb_state *usb, } /* Remove the transaction from the pipe list */ - if (transaction->next) - transaction->next->prev = transaction->prev; - else - pipe->tail = transaction->prev; - if (transaction->prev) - transaction->prev->next = transaction->next; - else - pipe->head = transaction->next; - if (!pipe->head) { - __cvmx_usb_remove_pipe(usb->active_pipes + pipe->transfer_type, pipe); - __cvmx_usb_append_pipe(&usb->idle_pipes, pipe); - - } + list_del(&transaction->node); + if (list_empty(&pipe->transactions)) + list_move_tail(&pipe->node, &usb->idle_pipes); octeon_usb_urb_complete_callback(usb, complete_code, pipe, transaction, transaction->actual_bytes, transaction->urb); - __cvmx_usb_free_transaction(usb, transaction); + kfree(transaction); done: return; } @@ -2311,13 +2156,10 @@ static struct cvmx_usb_transaction *__cvmx_usb_submit_transaction(struct cvmx_us { struct cvmx_usb_transaction *transaction; - /* Fail if the pipe isn't open */ - if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - return NULL; if (unlikely(pipe->transfer_type != type)) return NULL; - transaction = __cvmx_usb_alloc_transaction(usb); + transaction = kzalloc(sizeof(*transaction), GFP_ATOMIC); if (unlikely(!transaction)) return NULL; @@ -2335,24 +2177,19 @@ static struct cvmx_usb_transaction *__cvmx_usb_submit_transaction(struct cvmx_us else transaction->stage = CVMX_USB_STAGE_NON_CONTROL; - transaction->next = NULL; - if (pipe->tail) { - transaction->prev = pipe->tail; - transaction->prev->next = transaction; + if (!list_empty(&pipe->transactions)) { + list_add_tail(&transaction->node, &pipe->transactions); } else { - if (pipe->next_tx_frame < usb->frame_number) - pipe->next_tx_frame = usb->frame_number + pipe->interval - - (usb->frame_number - pipe->next_tx_frame) % pipe->interval; - transaction->prev = NULL; - pipe->head = transaction; - __cvmx_usb_remove_pipe(&usb->idle_pipes, pipe); - __cvmx_usb_append_pipe(usb->active_pipes + pipe->transfer_type, pipe); - } - pipe->tail = transaction; + list_add_tail(&transaction->node, &pipe->transactions); + list_move_tail(&pipe->node, + &usb->active_pipes[pipe->transfer_type]); - /* We may need to schedule the pipe if this was the head of the pipe */ - if (!transaction->prev) + /* + * We may need to schedule the pipe if this was the head of the + * pipe. + */ __cvmx_usb_schedule(usb, 0); + } return transaction; } @@ -2483,20 +2320,12 @@ static int cvmx_usb_cancel(struct cvmx_usb_state *usb, struct cvmx_usb_pipe *pipe, struct cvmx_usb_transaction *transaction) { - /* Fail if the pipe isn't open */ - if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - return -EINVAL; - - /* Fail if this transaction already completed */ - if (unlikely((transaction->flags & __CVMX_USB_TRANSACTION_FLAGS_IN_USE) == 0)) - return -EINVAL; - /* * If the transaction is the HEAD of the queue and scheduled. We need to * treat it special */ - if ((pipe->head == transaction) && - (pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) { + if (list_first_entry(&pipe->transactions, typeof(*transaction), node) == + transaction && (pipe->flags & __CVMX_USB_PIPE_FLAGS_SCHEDULED)) { union cvmx_usbcx_hccharx usbc_hcchar; usb->pipe_for_channel[pipe->channel] = NULL; @@ -2531,13 +2360,11 @@ static int cvmx_usb_cancel(struct cvmx_usb_state *usb, static int cvmx_usb_cancel_all(struct cvmx_usb_state *usb, struct cvmx_usb_pipe *pipe) { - /* Fail if the pipe isn't open */ - if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - return -EINVAL; + struct cvmx_usb_transaction *transaction, *next; /* Simply loop through and attempt to cancel each transaction */ - while (pipe->head) { - int result = cvmx_usb_cancel(usb, pipe, pipe->head); + list_for_each_entry_safe(transaction, next, &pipe->transactions, node) { + int result = cvmx_usb_cancel(usb, pipe, transaction); if (unlikely(result != 0)) return result; } @@ -2557,17 +2384,12 @@ static int cvmx_usb_cancel_all(struct cvmx_usb_state *usb, static int cvmx_usb_close_pipe(struct cvmx_usb_state *usb, struct cvmx_usb_pipe *pipe) { - /* Fail if the pipe isn't open */ - if (unlikely((pipe->flags & __CVMX_USB_PIPE_FLAGS_OPEN) == 0)) - return -EINVAL; - /* Fail if the pipe has pending transactions */ - if (unlikely(pipe->head)) + if (!list_empty(&pipe->transactions)) return -EBUSY; - pipe->flags = 0; - __cvmx_usb_remove_pipe(&usb->idle_pipes, pipe); - __cvmx_usb_append_pipe(&usb->free_pipes, pipe); + list_del(&pipe->node); + kfree(pipe); return 0; } @@ -2671,7 +2493,8 @@ static int __cvmx_usb_poll_channel(struct cvmx_usb_state *usb, int channel) CVMX_PREFETCH(pipe, 128); if (!pipe) return 0; - transaction = pipe->head; + transaction = list_first_entry(&pipe->transactions, typeof(*transaction), + node); CVMX_PREFETCH(transaction, 0); /* @@ -3338,16 +3161,15 @@ static int octeon_usb_urb_enqueue(struct usb_hcd *hcd, static void octeon_usb_urb_dequeue_work(unsigned long arg) { + struct urb *urb; + struct urb *next; unsigned long flags; struct octeon_hcd *priv = (struct octeon_hcd *)arg; spin_lock_irqsave(&priv->lock, flags); - while (!list_empty(&priv->dequeue_list)) { - struct urb *urb = container_of(priv->dequeue_list.next, struct urb, urb_list); - list_del(&urb->urb_list); - /* not enqueued on dequeue_list */ - INIT_LIST_HEAD(&urb->urb_list); + list_for_each_entry_safe(urb, next, &priv->dequeue_list, urb_list) { + list_del_init(&urb->urb_list); cvmx_usb_cancel(&priv->usb, urb->ep->hcpriv, urb->hcpriv); } diff --git a/drivers/staging/octeon-usb/cvmx-usbcx-defs.h b/drivers/staging/octeon-usb/octeon-hcd.h index d349d77bc359..42fe4fec7d5d 100644 --- a/drivers/staging/octeon-usb/cvmx-usbcx-defs.h +++ b/drivers/staging/octeon-usb/octeon-hcd.h @@ -1,7 +1,14 @@ -/***********************license start*************** - * Copyright (c) 2003-2010 Cavium Networks ([email protected]). All rights - * reserved. +/* + * Octeon HCD hardware register definitions. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. * + * Some parts of the code were originally released under BSD license: + * + * Copyright (c) 2003-2010 Cavium Networks ([email protected]). All rights + * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -14,17 +21,17 @@ * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. - + * * * Neither the name of Cavium Networks nor the names of * its contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. - + * * This Software, including technical data, may be subject to U.S. export * control laws, including the U.S. Export Administration Act and its associated - * regulations, and may be subject to export or import regulations in other + * regulations, and may be subject to export or import regulations in other * countries. - + * * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO @@ -33,20 +40,12 @@ * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR - * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR + * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. - ***********************license end**************************************/ - - -/** - * cvmx-usbcx-defs.h - * - * Configuration and status register (CSR) type definitions for - * Octeon usbcx. - * */ -#ifndef __CVMX_USBCX_TYPEDEFS_H__ -#define __CVMX_USBCX_TYPEDEFS_H__ + +#ifndef __OCTEON_HCD_H__ +#define __OCTEON_HCD_H__ #define CVMX_USBCXBASE 0x00016F0010000000ull #define CVMX_USBCXREG1(reg, bid) \ @@ -81,6 +80,19 @@ #define CVMX_USBCX_HPTXFSIZ(bid) CVMX_USBCXREG1(0x100, bid) #define CVMX_USBCX_HPTXSTS(bid) CVMX_USBCXREG1(0x410, bid) +#define CVMX_USBNXBID1(bid) (((bid) & 1) * 0x10000000ull) +#define CVMX_USBNXBID2(bid) (((bid) & 1) * 0x100000000000ull) + +#define CVMX_USBNXREG1(reg, bid) \ + (CVMX_ADD_IO_SEG(0x0001180068000000ull | reg) + CVMX_USBNXBID1(bid)) +#define CVMX_USBNXREG2(reg, bid) \ + (CVMX_ADD_IO_SEG(0x00016F0000000000ull | reg) + CVMX_USBNXBID2(bid)) + +#define CVMX_USBNX_CLK_CTL(bid) CVMX_USBNXREG1(0x10, bid) +#define CVMX_USBNX_DMA0_INB_CHN0(bid) CVMX_USBNXREG2(0x818, bid) +#define CVMX_USBNX_DMA0_OUTB_CHN0(bid) CVMX_USBNXREG2(0x858, bid) +#define CVMX_USBNX_USBP_CTL_STATUS(bid) CVMX_USBNXREG1(0x18, bid) + /** * cvmx_usbc#_gahbcfg * @@ -1525,4 +1537,283 @@ union cvmx_usbcx_hptxsts { } s; }; -#endif +/** + * cvmx_usbn#_clk_ctl + * + * USBN_CLK_CTL = USBN's Clock Control + * + * This register is used to control the frequency of the hclk and the + * hreset and phy_rst signals. + */ +union cvmx_usbnx_clk_ctl { + uint64_t u64; + /** + * struct cvmx_usbnx_clk_ctl_s + * @divide2: The 'hclk' used by the USB subsystem is derived + * from the eclk. + * Also see the field DIVIDE. DIVIDE2<1> must currently + * be zero because it is not implemented, so the maximum + * ratio of eclk/hclk is currently 16. + * The actual divide number for hclk is: + * (DIVIDE2 + 1) * (DIVIDE + 1) + * @hclk_rst: When this field is '0' the HCLK-DIVIDER used to + * generate the hclk in the USB Subsystem is held + * in reset. This bit must be set to '0' before + * changing the value os DIVIDE in this register. + * The reset to the HCLK_DIVIDERis also asserted + * when core reset is asserted. + * @p_x_on: Force USB-PHY on during suspend. + * '1' USB-PHY XO block is powered-down during + * suspend. + * '0' USB-PHY XO block is powered-up during + * suspend. + * The value of this field must be set while POR is + * active. + * @p_rtype: PHY reference clock type + * On CN50XX/CN52XX/CN56XX the values are: + * '0' The USB-PHY uses a 12MHz crystal as a clock source + * at the USB_XO and USB_XI pins. + * '1' Reserved. + * '2' The USB_PHY uses 12/24/48MHz 2.5V board clock at the + * USB_XO pin. USB_XI should be tied to ground in this + * case. + * '3' Reserved. + * On CN3xxx bits 14 and 15 are p_xenbn and p_rclk and values are: + * '0' Reserved. + * '1' Reserved. + * '2' The PHY PLL uses the XO block output as a reference. + * The XO block uses an external clock supplied on the + * XO pin. USB_XI should be tied to ground for this + * usage. + * '3' The XO block uses the clock from a crystal. + * @p_com_on: '0' Force USB-PHY XO Bias, Bandgap and PLL to + * remain powered in Suspend Mode. + * '1' The USB-PHY XO Bias, Bandgap and PLL are + * powered down in suspend mode. + * The value of this field must be set while POR is + * active. + * @p_c_sel: Phy clock speed select. + * Selects the reference clock / crystal frequency. + * '11': Reserved + * '10': 48 MHz (reserved when a crystal is used) + * '01': 24 MHz (reserved when a crystal is used) + * '00': 12 MHz + * The value of this field must be set while POR is + * active. + * NOTE: if a crystal is used as a reference clock, + * this field must be set to 12 MHz. + * @cdiv_byp: Used to enable the bypass input to the USB_CLK_DIV. + * @sd_mode: Scaledown mode for the USBC. Control timing events + * in the USBC, for normal operation this must be '0'. + * @s_bist: Starts bist on the hclk memories, during the '0' + * to '1' transition. + * @por: Power On Reset for the PHY. + * Resets all the PHYS registers and state machines. + * @enable: When '1' allows the generation of the hclk. When + * '0' the hclk will not be generated. SEE DIVIDE + * field of this register. + * @prst: When this field is '0' the reset associated with + * the phy_clk functionality in the USB Subsystem is + * help in reset. This bit should not be set to '1' + * until the time it takes 6 clocks (hclk or phy_clk, + * whichever is slower) has passed. Under normal + * operation once this bit is set to '1' it should not + * be set to '0'. + * @hrst: When this field is '0' the reset associated with + * the hclk functioanlity in the USB Subsystem is + * held in reset.This bit should not be set to '1' + * until 12ms after phy_clk is stable. Under normal + * operation, once this bit is set to '1' it should + * not be set to '0'. + * @divide: The frequency of 'hclk' used by the USB subsystem + * is the eclk frequency divided by the value of + * (DIVIDE2 + 1) * (DIVIDE + 1), also see the field + * DIVIDE2 of this register. + * The hclk frequency should be less than 125Mhz. + * After writing a value to this field the SW should + * read the field for the value written. + * The ENABLE field of this register should not be set + * until AFTER this field is set and then read. + */ + struct cvmx_usbnx_clk_ctl_s { + uint64_t reserved_20_63 : 44; + uint64_t divide2 : 2; + uint64_t hclk_rst : 1; + uint64_t p_x_on : 1; + uint64_t p_rtype : 2; + uint64_t p_com_on : 1; + uint64_t p_c_sel : 2; + uint64_t cdiv_byp : 1; + uint64_t sd_mode : 2; + uint64_t s_bist : 1; + uint64_t por : 1; + uint64_t enable : 1; + uint64_t prst : 1; + uint64_t hrst : 1; + uint64_t divide : 3; + } s; +}; + +/** + * cvmx_usbn#_usbp_ctl_status + * + * USBN_USBP_CTL_STATUS = USBP Control And Status Register + * + * Contains general control and status information for the USBN block. + */ +union cvmx_usbnx_usbp_ctl_status { + uint64_t u64; + /** + * struct cvmx_usbnx_usbp_ctl_status_s + * @txrisetune: HS Transmitter Rise/Fall Time Adjustment + * @txvreftune: HS DC Voltage Level Adjustment + * @txfslstune: FS/LS Source Impedence Adjustment + * @txhsxvtune: Transmitter High-Speed Crossover Adjustment + * @sqrxtune: Squelch Threshold Adjustment + * @compdistune: Disconnect Threshold Adjustment + * @otgtune: VBUS Valid Threshold Adjustment + * @otgdisable: OTG Block Disable + * @portreset: Per_Port Reset + * @drvvbus: Drive VBUS + * @lsbist: Low-Speed BIST Enable. + * @fsbist: Full-Speed BIST Enable. + * @hsbist: High-Speed BIST Enable. + * @bist_done: PHY Bist Done. + * Asserted at the end of the PHY BIST sequence. + * @bist_err: PHY Bist Error. + * Indicates an internal error was detected during + * the BIST sequence. + * @tdata_out: PHY Test Data Out. + * Presents either internaly generated signals or + * test register contents, based upon the value of + * test_data_out_sel. + * @siddq: Drives the USBP (USB-PHY) SIDDQ input. + * Normally should be set to zero. + * When customers have no intent to use USB PHY + * interface, they should: + * - still provide 3.3V to USB_VDD33, and + * - tie USB_REXT to 3.3V supply, and + * - set USBN*_USBP_CTL_STATUS[SIDDQ]=1 + * @txpreemphasistune: HS Transmitter Pre-Emphasis Enable + * @dma_bmode: When set to 1 the L2C DMA address will be updated + * with byte-counts between packets. When set to 0 + * the L2C DMA address is incremented to the next + * 4-byte aligned address after adding byte-count. + * @usbc_end: Bigendian input to the USB Core. This should be + * set to '0' for operation. + * @usbp_bist: PHY, This is cleared '0' to run BIST on the USBP. + * @tclk: PHY Test Clock, used to load TDATA_IN to the USBP. + * @dp_pulld: PHY DP_PULLDOWN input to the USB-PHY. + * This signal enables the pull-down resistance on + * the D+ line. '1' pull down-resistance is connected + * to D+/ '0' pull down resistance is not connected + * to D+. When an A/B device is acting as a host + * (downstream-facing port), dp_pulldown and + * dm_pulldown are enabled. This must not toggle + * during normal opeartion. + * @dm_pulld: PHY DM_PULLDOWN input to the USB-PHY. + * This signal enables the pull-down resistance on + * the D- line. '1' pull down-resistance is connected + * to D-. '0' pull down resistance is not connected + * to D-. When an A/B device is acting as a host + * (downstream-facing port), dp_pulldown and + * dm_pulldown are enabled. This must not toggle + * during normal opeartion. + * @hst_mode: When '0' the USB is acting as HOST, when '1' + * USB is acting as device. This field needs to be + * set while the USB is in reset. + * @tuning: Transmitter Tuning for High-Speed Operation. + * Tunes the current supply and rise/fall output + * times for high-speed operation. + * [20:19] == 11: Current supply increased + * approximately 9% + * [20:19] == 10: Current supply increased + * approximately 4.5% + * [20:19] == 01: Design default. + * [20:19] == 00: Current supply decreased + * approximately 4.5% + * [22:21] == 11: Rise and fall times are increased. + * [22:21] == 10: Design default. + * [22:21] == 01: Rise and fall times are decreased. + * [22:21] == 00: Rise and fall times are decreased + * further as compared to the 01 setting. + * @tx_bs_enh: Transmit Bit Stuffing on [15:8]. + * Enables or disables bit stuffing on data[15:8] + * when bit-stuffing is enabled. + * @tx_bs_en: Transmit Bit Stuffing on [7:0]. + * Enables or disables bit stuffing on data[7:0] + * when bit-stuffing is enabled. + * @loop_enb: PHY Loopback Test Enable. + * '1': During data transmission the receive is + * enabled. + * '0': During data transmission the receive is + * disabled. + * Must be '0' for normal operation. + * @vtest_enb: Analog Test Pin Enable. + * '1' The PHY's analog_test pin is enabled for the + * input and output of applicable analog test signals. + * '0' THe analog_test pin is disabled. + * @bist_enb: Built-In Self Test Enable. + * Used to activate BIST in the PHY. + * @tdata_sel: Test Data Out Select. + * '1' test_data_out[3:0] (PHY) register contents + * are output. '0' internaly generated signals are + * output. + * @taddr_in: Mode Address for Test Interface. + * Specifies the register address for writing to or + * reading from the PHY test interface register. + * @tdata_in: Internal Testing Register Input Data and Select + * This is a test bus. Data is present on [3:0], + * and its corresponding select (enable) is present + * on bits [7:4]. + * @ate_reset: Reset input from automatic test equipment. + * This is a test signal. When the USB Core is + * powered up (not in Susned Mode), an automatic + * tester can use this to disable phy_clock and + * free_clk, then re-eanable them with an aligned + * phase. + * '1': The phy_clk and free_clk outputs are + * disabled. "0": The phy_clock and free_clk outputs + * are available within a specific period after the + * de-assertion. + */ + struct cvmx_usbnx_usbp_ctl_status_s { + uint64_t txrisetune : 1; + uint64_t txvreftune : 4; + uint64_t txfslstune : 4; + uint64_t txhsxvtune : 2; + uint64_t sqrxtune : 3; + uint64_t compdistune : 3; + uint64_t otgtune : 3; + uint64_t otgdisable : 1; + uint64_t portreset : 1; + uint64_t drvvbus : 1; + uint64_t lsbist : 1; + uint64_t fsbist : 1; + uint64_t hsbist : 1; + uint64_t bist_done : 1; + uint64_t bist_err : 1; + uint64_t tdata_out : 4; + uint64_t siddq : 1; + uint64_t txpreemphasistune : 1; + uint64_t dma_bmode : 1; + uint64_t usbc_end : 1; + uint64_t usbp_bist : 1; + uint64_t tclk : 1; + uint64_t dp_pulld : 1; + uint64_t dm_pulld : 1; + uint64_t hst_mode : 1; + uint64_t tuning : 4; + uint64_t tx_bs_enh : 1; + uint64_t tx_bs_en : 1; + uint64_t loop_enb : 1; + uint64_t vtest_enb : 1; + uint64_t bist_enb : 1; + uint64_t tdata_sel : 1; + uint64_t taddr_in : 4; + uint64_t tdata_in : 8; + uint64_t ate_reset : 1; + } s; +}; + +#endif /* __OCTEON_HCD_H__ */ diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c index af8d62818f13..5108bc0bb573 100644 --- a/drivers/staging/octeon/ethernet-spi.c +++ b/drivers/staging/octeon/ethernet-spi.c @@ -64,31 +64,23 @@ static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) if (spx_int_reg.s.spf) pr_err("SPI1: SRX Spi4 interface down\n"); if (spx_int_reg.s.calerr) - pr_err("SPI1: SRX Spi4 Calendar table " - "parity error\n"); + pr_err("SPI1: SRX Spi4 Calendar table parity error\n"); if (spx_int_reg.s.syncerr) - pr_err("SPI1: SRX Consecutive Spi4 DIP4 " - "errors have exceeded " - "SPX_ERR_CTL[ERRCNT]\n"); + pr_err("SPI1: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n"); if (spx_int_reg.s.diperr) pr_err("SPI1: SRX Spi4 DIP4 error\n"); if (spx_int_reg.s.tpaovr) - pr_err("SPI1: SRX Selected port has hit " - "TPA overflow\n"); + pr_err("SPI1: SRX Selected port has hit TPA overflow\n"); if (spx_int_reg.s.rsverr) - pr_err("SPI1: SRX Spi4 reserved control " - "word detected\n"); + pr_err("SPI1: SRX Spi4 reserved control word detected\n"); if (spx_int_reg.s.drwnng) - pr_err("SPI1: SRX Spi4 receive FIFO " - "drowning/overflow\n"); + pr_err("SPI1: SRX Spi4 receive FIFO drowning/overflow\n"); if (spx_int_reg.s.clserr) - pr_err("SPI1: SRX Spi4 packet closed on " - "non-16B alignment without EOP\n"); + pr_err("SPI1: SRX Spi4 packet closed on non-16B alignment without EOP\n"); if (spx_int_reg.s.spiovr) pr_err("SPI1: SRX Spi4 async FIFO overflow\n"); if (spx_int_reg.s.abnorm) - pr_err("SPI1: SRX Abnormal packet " - "termination (ERR bit)\n"); + pr_err("SPI1: SRX Abnormal packet termination (ERR bit)\n"); if (spx_int_reg.s.prtnxa) pr_err("SPI1: SRX Port out of range\n"); } @@ -99,31 +91,23 @@ static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(1)); if (stx_int_reg.s.syncerr) - pr_err("SPI1: STX Interface encountered a " - "fatal error\n"); + pr_err("SPI1: STX Interface encountered a fatal error\n"); if (stx_int_reg.s.frmerr) - pr_err("SPI1: STX FRMCNT has exceeded " - "STX_DIP_CNT[MAXFRM]\n"); + pr_err("SPI1: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n"); if (stx_int_reg.s.unxfrm) - pr_err("SPI1: STX Unexpected framing " - "sequence\n"); + pr_err("SPI1: STX Unexpected framing sequence\n"); if (stx_int_reg.s.nosync) - pr_err("SPI1: STX ERRCNT has exceeded " - "STX_DIP_CNT[MAXDIP]\n"); + pr_err("SPI1: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n"); if (stx_int_reg.s.diperr) - pr_err("SPI1: STX DIP2 error on the Spi4 " - "Status channel\n"); + pr_err("SPI1: STX DIP2 error on the Spi4 Status channel\n"); if (stx_int_reg.s.datovr) pr_err("SPI1: STX Spi4 FIFO overflow error\n"); if (stx_int_reg.s.ovrbst) - pr_err("SPI1: STX Transmit packet burst " - "too big\n"); + pr_err("SPI1: STX Transmit packet burst too big\n"); if (stx_int_reg.s.calpar1) - pr_err("SPI1: STX Calendar Table Parity " - "Error Bank1\n"); + pr_err("SPI1: STX Calendar Table Parity Error Bank1\n"); if (stx_int_reg.s.calpar0) - pr_err("SPI1: STX Calendar Table Parity " - "Error Bank0\n"); + pr_err("SPI1: STX Calendar Table Parity Error Bank0\n"); } cvmx_write_csr(CVMX_SPXX_INT_MSK(1), 0); @@ -144,31 +128,23 @@ static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) if (spx_int_reg.s.spf) pr_err("SPI0: SRX Spi4 interface down\n"); if (spx_int_reg.s.calerr) - pr_err("SPI0: SRX Spi4 Calendar table " - "parity error\n"); + pr_err("SPI0: SRX Spi4 Calendar table parity error\n"); if (spx_int_reg.s.syncerr) - pr_err("SPI0: SRX Consecutive Spi4 DIP4 " - "errors have exceeded " - "SPX_ERR_CTL[ERRCNT]\n"); + pr_err("SPI0: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n"); if (spx_int_reg.s.diperr) pr_err("SPI0: SRX Spi4 DIP4 error\n"); if (spx_int_reg.s.tpaovr) - pr_err("SPI0: SRX Selected port has hit " - "TPA overflow\n"); + pr_err("SPI0: SRX Selected port has hit TPA overflow\n"); if (spx_int_reg.s.rsverr) - pr_err("SPI0: SRX Spi4 reserved control " - "word detected\n"); + pr_err("SPI0: SRX Spi4 reserved control word detected\n"); if (spx_int_reg.s.drwnng) - pr_err("SPI0: SRX Spi4 receive FIFO " - "drowning/overflow\n"); + pr_err("SPI0: SRX Spi4 receive FIFO drowning/overflow\n"); if (spx_int_reg.s.clserr) - pr_err("SPI0: SRX Spi4 packet closed on " - "non-16B alignment without EOP\n"); + pr_err("SPI0: SRX Spi4 packet closed on non-16B alignment without EOP\n"); if (spx_int_reg.s.spiovr) pr_err("SPI0: SRX Spi4 async FIFO overflow\n"); if (spx_int_reg.s.abnorm) - pr_err("SPI0: SRX Abnormal packet " - "termination (ERR bit)\n"); + pr_err("SPI0: SRX Abnormal packet termination (ERR bit)\n"); if (spx_int_reg.s.prtnxa) pr_err("SPI0: SRX Port out of range\n"); } @@ -179,31 +155,23 @@ static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id) stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(0)); if (stx_int_reg.s.syncerr) - pr_err("SPI0: STX Interface encountered a " - "fatal error\n"); + pr_err("SPI0: STX Interface encountered a fatal error\n"); if (stx_int_reg.s.frmerr) - pr_err("SPI0: STX FRMCNT has exceeded " - "STX_DIP_CNT[MAXFRM]\n"); + pr_err("SPI0: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n"); if (stx_int_reg.s.unxfrm) - pr_err("SPI0: STX Unexpected framing " - "sequence\n"); + pr_err("SPI0: STX Unexpected framing sequence\n"); if (stx_int_reg.s.nosync) - pr_err("SPI0: STX ERRCNT has exceeded " - "STX_DIP_CNT[MAXDIP]\n"); + pr_err("SPI0: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n"); if (stx_int_reg.s.diperr) - pr_err("SPI0: STX DIP2 error on the Spi4 " - "Status channel\n"); + pr_err("SPI0: STX DIP2 error on the Spi4 Status channel\n"); if (stx_int_reg.s.datovr) pr_err("SPI0: STX Spi4 FIFO overflow error\n"); if (stx_int_reg.s.ovrbst) - pr_err("SPI0: STX Transmit packet burst " - "too big\n"); + pr_err("SPI0: STX Transmit packet burst too big\n"); if (stx_int_reg.s.calpar1) - pr_err("SPI0: STX Calendar Table Parity " - "Error Bank1\n"); + pr_err("SPI0: STX Calendar Table Parity Error Bank1\n"); if (stx_int_reg.s.calpar0) - pr_err("SPI0: STX Calendar Table Parity " - "Error Bank0\n"); + pr_err("SPI0: STX Calendar Table Parity Error Bank0\n"); } cvmx_write_csr(CVMX_SPXX_INT_MSK(0), 0); diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index dbfef1a05176..9b4d0b546b89 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -78,10 +78,12 @@ static DECLARE_TASKLET(cvm_oct_tx_cleanup_tasklet, cvm_oct_tx_do_cleanup, 0); static inline int32_t cvm_oct_adjust_skb_to_free(int32_t skb_to_free, int fau) { int32_t undo; - undo = skb_to_free > 0 ? MAX_SKB_TO_FREE : skb_to_free + MAX_SKB_TO_FREE; + undo = skb_to_free > 0 ? MAX_SKB_TO_FREE : skb_to_free + + MAX_SKB_TO_FREE; if (undo > 0) cvmx_fau_atomic_add32(fau, -undo); - skb_to_free = -skb_to_free > MAX_SKB_TO_FREE ? MAX_SKB_TO_FREE : -skb_to_free; + skb_to_free = -skb_to_free > MAX_SKB_TO_FREE ? MAX_SKB_TO_FREE : + -skb_to_free; return skb_to_free; } @@ -108,8 +110,10 @@ void cvm_oct_free_tx_skbs(struct net_device *dev) for (qos = 0; qos < queues_per_port; qos++) { if (skb_queue_len(&priv->tx_free_list[qos]) == 0) continue; - skb_to_free = cvmx_fau_fetch_and_add32(priv->fau+qos*4, MAX_SKB_TO_FREE); - skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, priv->fau+qos*4); + skb_to_free = cvmx_fau_fetch_and_add32(priv->fau+qos*4, + MAX_SKB_TO_FREE); + skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, + priv->fau+qos*4); total_freed += skb_to_free; @@ -117,12 +121,14 @@ void cvm_oct_free_tx_skbs(struct net_device *dev) struct sk_buff *to_free_list = NULL; spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); while (skb_to_free > 0) { - struct sk_buff *t = __skb_dequeue(&priv->tx_free_list[qos]); + struct sk_buff *t; + t = __skb_dequeue(&priv->tx_free_list[qos]); t->next = to_free_list; to_free_list = t; skb_to_free--; } - spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, flags); + spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, + flags); /* Do the actual freeing outside of the lock. */ while (to_free_list) { struct sk_buff *t = to_free_list; @@ -211,15 +217,23 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(__skb_linearize(skb))) { queue_type = QUEUE_DROP; if (USE_ASYNC_IOBDMA) { - /* Get the number of skbuffs in use by the hardware */ + /* + * Get the number of skbuffs in use + * by the hardware + */ CVMX_SYNCIOBDMA; - skb_to_free = cvmx_scratch_read64(CVMX_SCR_SCRATCH); + skb_to_free = + cvmx_scratch_read64(CVMX_SCR_SCRATCH); } else { - /* Get the number of skbuffs in use by the hardware */ - skb_to_free = cvmx_fau_fetch_and_add32(priv->fau + qos * 4, - MAX_SKB_TO_FREE); + /* + * Get the number of skbuffs in use + * by the hardware + */ + skb_to_free = cvmx_fau_fetch_and_add32( + priv->fau + qos * 4, MAX_SKB_TO_FREE); } - skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, priv->fau + qos * 4); + skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, + priv->fau + qos * 4); spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); goto skip_xmit; } @@ -276,7 +290,9 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) CVM_OCT_SKB_CB(skb)[0] = hw_buffer.u64; for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { struct skb_frag_struct *fs = skb_shinfo(skb)->frags + i; - hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)(page_address(fs->page.p) + fs->page_offset)); + hw_buffer.s.addr = XKPHYS_TO_PHYS( + (u64)(page_address(fs->page.p) + + fs->page_offset)); hw_buffer.s.size = fs->size; CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64; } @@ -358,7 +374,9 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) */ pko_command.s.dontfree = 0; - hw_buffer.s.back = ((unsigned long)skb->data >> 7) - ((unsigned long)fpa_head >> 7); + hw_buffer.s.back = ((unsigned long)skb->data >> 7) - + ((unsigned long)fpa_head >> 7); + *(struct sk_buff **)(fpa_head - sizeof(void *)) = skb; /* @@ -422,17 +440,22 @@ dont_put_skbuff_in_hw: queue_type = QUEUE_HW; } if (USE_ASYNC_IOBDMA) - cvmx_fau_async_fetch_and_add32(CVMX_SCR_SCRATCH, FAU_TOTAL_TX_TO_CLEAN, 1); + cvmx_fau_async_fetch_and_add32( + CVMX_SCR_SCRATCH, FAU_TOTAL_TX_TO_CLEAN, 1); spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); /* Drop this packet if we have too many already queued to the HW */ - if (unlikely(skb_queue_len(&priv->tx_free_list[qos]) >= MAX_OUT_QUEUE_DEPTH)) { + if (unlikely(skb_queue_len(&priv->tx_free_list[qos]) >= + MAX_OUT_QUEUE_DEPTH)) { + if (dev->tx_queue_len != 0) { /* Drop the lock when notifying the core. */ - spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, flags); + spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, + flags); netif_stop_queue(dev); - spin_lock_irqsave(&priv->tx_free_list[qos].lock, flags); + spin_lock_irqsave(&priv->tx_free_list[qos].lock, + flags); } else { /* If not using normal queueing. */ queue_type = QUEUE_DROP; @@ -448,7 +471,8 @@ dont_put_skbuff_in_hw: priv->queue + qos, pko_command, hw_buffer, CVMX_PKO_LOCK_NONE))) { - printk_ratelimited("%s: Failed to send the packet\n", dev->name); + printk_ratelimited("%s: Failed to send the packet\n", + dev->name); queue_type = QUEUE_DROP; } skip_xmit: @@ -493,7 +517,8 @@ skip_xmit: cvmx_scratch_write64(CVMX_SCR_SCRATCH, old_scratch); cvmx_scratch_write64(CVMX_SCR_SCRATCH + 8, old_scratch2); } else { - total_to_clean = cvmx_fau_fetch_and_add32(FAU_TOTAL_TX_TO_CLEAN, 1); + total_to_clean = cvmx_fau_fetch_and_add32( + FAU_TOTAL_TX_TO_CLEAN, 1); } if (total_to_clean & 0x3ff) { @@ -527,8 +552,8 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev) /* Get a work queue entry */ cvmx_wqe_t *work = cvmx_fpa_alloc(CVMX_FPA_WQE_POOL); if (unlikely(work == NULL)) { - printk_ratelimited("%s: Failed to allocate a work " - "queue entry\n", dev->name); + printk_ratelimited("%s: Failed to allocate a work queue entry\n", + dev->name); priv->stats.tx_dropped++; dev_kfree_skb(skb); return 0; diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index c3a90e7012af..8aba66e4a3e4 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -163,11 +163,13 @@ static void cvm_oct_periodic_worker(struct work_struct *work) if (priv->poll) priv->poll(cvm_oct_device[priv->port]); - cvm_oct_device[priv->port]->netdev_ops->ndo_get_stats(cvm_oct_device[priv->port]); + cvm_oct_device[priv->port]->netdev_ops->ndo_get_stats( + cvm_oct_device[priv->port]); if (!atomic_read(&cvm_oct_poll_queue_stopping)) - queue_delayed_work(cvm_oct_poll_queue, &priv->port_periodic_work, HZ); - } + queue_delayed_work(cvm_oct_poll_queue, + &priv->port_periodic_work, HZ); +} static void cvm_oct_configure_common_hw(void) { @@ -584,8 +586,8 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = { extern void octeon_mdiobus_force_mod_depencency(void); -static struct device_node *cvm_oct_of_get_child(const struct device_node *parent, - int reg_val) +static struct device_node *cvm_oct_of_get_child( + const struct device_node *parent, int reg_val) { struct device_node *node = NULL; int size; @@ -603,7 +605,7 @@ static struct device_node *cvm_oct_of_get_child(const struct device_node *parent } static struct device_node *cvm_oct_node_for_port(struct device_node *pip, - int interface, int port) + int interface, int port) { struct device_node *ni, *np; @@ -713,7 +715,8 @@ static int cvm_oct_probe(struct platform_device *pdev) int port; int port_index; - for (port_index = 0, port = cvmx_helper_get_ipd_port(interface, 0); + for (port_index = 0, + port = cvmx_helper_get_ipd_port(interface, 0); port < cvmx_helper_get_ipd_port(interface, num_ports); port_index++, port++) { struct octeon_ethernet *priv; @@ -726,7 +729,8 @@ static int cvm_oct_probe(struct platform_device *pdev) /* Initialize the device private structure. */ priv = netdev_priv(dev); - priv->of_node = cvm_oct_node_for_port(pip, interface, port_index); + priv->of_node = cvm_oct_node_for_port(pip, interface, + port_index); INIT_DELAYED_WORK(&priv->port_periodic_work, cvm_oct_periodic_worker); @@ -793,7 +797,7 @@ static int cvm_oct_probe(struct platform_device *pdev) cvmx_pko_get_num_queues(priv->port) * sizeof(uint32_t); queue_delayed_work(cvm_oct_poll_queue, - &priv->port_periodic_work, HZ); + &priv->port_periodic_work, HZ); } } } diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig index 28aa42c77a9f..d277f048789e 100644 --- a/drivers/staging/olpc_dcon/Kconfig +++ b/drivers/staging/olpc_dcon/Kconfig @@ -1,8 +1,8 @@ config FB_OLPC_DCON tristate "One Laptop Per Child Display CONtroller support" depends on OLPC && FB + depends on I2C depends on (GPIO_CS5535 || GPIO_CS5535=n) - select I2C select BACKLIGHT_CLASS_DEVICE ---help--- In order to support very low power operation, the XO laptop uses a diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c index 978dc5f4f929..43383cf8b161 100644 --- a/drivers/staging/rtl8187se/r8185b_init.c +++ b/drivers/staging/rtl8187se/r8185b_init.c @@ -135,7 +135,7 @@ static void PlatformIOWrite2Byte(struct net_device *dev, u32 offset, u16 data) static void PlatformIOWrite4Byte(struct net_device *dev, u32 offset, u32 data) { if (offset == PhyAddr) { - /* For Base Band configuration. */ + /* For Base Band configuration. */ unsigned char cmdByte; unsigned long dataBytes; unsigned char idx; @@ -155,7 +155,7 @@ static void PlatformIOWrite4Byte(struct net_device *dev, u32 offset, u32 data) /* NdisAcquireSpinLock( &(pDevice->IoSpinLock) ); */ for (idx = 0; idx < 30; idx++) { - /* Make sure command bit is clear before access it. */ + /* Make sure command bit is clear before access it. */ u1bTmp = PlatformIORead1Byte(dev, PhyAddr); if ((u1bTmp & BIT7) == 0) break; @@ -1296,8 +1296,8 @@ void rtl8185b_rx_enable(struct net_device *dev) if (dev->flags & IFF_PROMISC) DMESG("NIC in promisc mode"); - if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || \ - dev->flags & IFF_PROMISC) { + if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || dev->flags & + IFF_PROMISC) { priv->ReceiveConfig = priv->ReceiveConfig & (~RCR_APM); priv->ReceiveConfig = priv->ReceiveConfig | RCR_AAP; } diff --git a/drivers/staging/rtl8188eu/Makefile b/drivers/staging/rtl8188eu/Makefile index 1639a45da948..0bd32de44600 100644 --- a/drivers/staging/rtl8188eu/Makefile +++ b/drivers/staging/rtl8188eu/Makefile @@ -30,7 +30,6 @@ r8188eu-y := \ hal/HalPhyRf.o \ hal/HalPhyRf_8188e.o \ hal/HalPwrSeqCmd.o \ - hal/Hal8188EFWImg_CE.o \ hal/Hal8188EPwrSeq.o \ hal/Hal8188ERateAdaptive.o\ hal/hal_intf.o \ diff --git a/drivers/staging/rtl8188eu/TODO b/drivers/staging/rtl8188eu/TODO index e50aa50bdb47..f7f389c40e71 100644 --- a/drivers/staging/rtl8188eu/TODO +++ b/drivers/staging/rtl8188eu/TODO @@ -2,7 +2,6 @@ TODO: - find and remove remaining code valid only for 5 HGz. Most of the obvious ones have been removed, but things like channel > 14 still exist. - find and remove any code for other chips that is left over -- convert to external firmware - convert any remaining unusual variable types - find codes that can use %pM and %Nph formatting - checkpatch.pl fixes - most of the remaining ones are lines too long. Many diff --git a/drivers/staging/rtl8188eu/core/rtw_cmd.c b/drivers/staging/rtl8188eu/core/rtw_cmd.c index 06be02c79ce8..f45f4eddb741 100644 --- a/drivers/staging/rtl8188eu/core/rtw_cmd.c +++ b/drivers/staging/rtl8188eu/core/rtw_cmd.c @@ -218,7 +218,7 @@ _func_enter_; _func_exit_; } -int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) +static int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj) { u8 bAllow = false; /* set to true to allow enqueuing cmd when hw_init_completed is false */ @@ -1667,7 +1667,7 @@ static void traffic_status_watchdog(struct adapter *padapter) pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic; } -void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz) +static void dynamic_chk_wk_hdl(struct adapter *padapter, u8 *pbuf, int sz) { struct mlme_priv *pmlmepriv; diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index ba8e53463d10..9f0f30f7069a 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -1586,7 +1586,7 @@ _func_enter_; pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len; plist = get_next(plist); - }; + } /* free the defrag_q queue and return the prframe */ rtw_free_recvframe_queue(defrag_q, pfree_recv_queue); diff --git a/drivers/staging/rtl8188eu/hal/Hal8188EFWImg_CE.c b/drivers/staging/rtl8188eu/hal/Hal8188EFWImg_CE.c deleted file mode 100644 index 95759bed5410..000000000000 --- a/drivers/staging/rtl8188eu/hal/Hal8188EFWImg_CE.c +++ /dev/null @@ -1,1761 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA -* -* -******************************************************************************/ -#include "odm_precomp.h" - -const u8 Rtl8188EFwImgArray[Rtl8188EFWImgArrayLength] = { - 0xE1, 0x88, 0x10, 0x00, 0x0B, 0x00, 0x01, 0x00, - 0x01, 0x21, 0x11, 0x27, 0x30, 0x36, 0x00, 0x00, - 0x2D, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x45, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xC1, 0x6F, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xA1, 0xE6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x56, 0xF7, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xC2, 0xAF, 0x80, 0xFE, 0x32, 0x12, 0x42, 0x04, - 0x85, 0xD0, 0x0B, 0x75, 0xD0, 0x08, 0xAA, 0xE0, - 0xC2, 0x8C, 0xE5, 0x8A, 0x24, 0x67, 0xF5, 0x8A, - 0xE5, 0x8C, 0x34, 0x79, 0xF5, 0x8C, 0xD2, 0x8C, - 0xEC, 0x24, 0x89, 0xF8, 0xE6, 0xBC, 0x03, 0x02, - 0x74, 0xFF, 0xC3, 0x95, 0x81, 0xB4, 0x40, 0x00, - 0x40, 0xCE, 0x79, 0x04, 0x78, 0x80, 0x16, 0xE6, - 0x08, 0x70, 0x0B, 0xC2, 0xAF, 0xE6, 0x30, 0xE1, - 0x03, 0x44, 0x18, 0xF6, 0xD2, 0xAF, 0x08, 0xD9, - 0xED, 0xEA, 0x8B, 0xD0, 0x22, 0xE5, 0x0C, 0xFF, - 0x23, 0x24, 0x81, 0xF8, 0x0F, 0x08, 0x08, 0xBF, - 0x04, 0x04, 0x7F, 0x00, 0x78, 0x81, 0xE6, 0x30, - 0xE4, 0xF2, 0x00, 0xE5, 0x0C, 0xC3, 0x9F, 0x50, - 0x20, 0x05, 0x0C, 0x74, 0x88, 0x25, 0x0C, 0xF8, - 0xE6, 0xFD, 0xA6, 0x81, 0x08, 0xE6, 0xAE, 0x0C, - 0xBE, 0x03, 0x02, 0x74, 0xFF, 0xCD, 0xF8, 0xE8, - 0x6D, 0x60, 0xE0, 0x08, 0xE6, 0xC0, 0xE0, 0x80, - 0xF6, 0xE5, 0x0C, 0xD3, 0x9F, 0x40, 0x27, 0xE5, - 0x0C, 0x24, 0x89, 0xF8, 0xE6, 0xAE, 0x0C, 0xBE, - 0x03, 0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xCD, - 0xF8, 0xE5, 0x81, 0x6D, 0x60, 0x06, 0xD0, 0xE0, - 0xF6, 0x18, 0x80, 0xF5, 0xE5, 0x0C, 0x24, 0x88, - 0xC8, 0xF6, 0x15, 0x0C, 0x80, 0xD3, 0xE5, 0x0C, - 0x23, 0x24, 0x81, 0xF8, 0x7F, 0x04, 0xC2, 0xAF, - 0xE6, 0x30, 0xE0, 0x03, 0x10, 0xE2, 0x0C, 0x7F, - 0x00, 0x30, 0xE1, 0x07, 0x30, 0xE3, 0x04, 0x7F, - 0x08, 0x54, 0xF4, 0x54, 0x7C, 0xC6, 0xD2, 0xAF, - 0x54, 0x80, 0x42, 0x07, 0x22, 0x78, 0x88, 0xA6, - 0x81, 0x74, 0x03, 0x60, 0x06, 0xFF, 0x08, 0x76, - 0xFF, 0xDF, 0xFB, 0x7F, 0x04, 0xE4, 0x78, 0x80, - 0xF6, 0x08, 0xF6, 0x08, 0xDF, 0xFA, 0x78, 0x81, - 0x76, 0x30, 0x90, 0x45, 0xDE, 0x74, 0x01, 0x93, - 0xC0, 0xE0, 0xE4, 0x93, 0xC0, 0xE0, 0x43, 0x89, - 0x01, 0x75, 0x8A, 0x60, 0x75, 0x8C, 0x79, 0xD2, - 0x8C, 0xD2, 0xAF, 0x22, 0x03, 0xEF, 0xD3, 0x94, - 0x03, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0x74, 0x81, - 0x2F, 0x2F, 0xF8, 0xE6, 0x20, 0xE5, 0xF4, 0xC2, - 0xAF, 0xE6, 0x44, 0x30, 0xF6, 0xD2, 0xAF, 0xAE, - 0x0C, 0xEE, 0xC3, 0x9F, 0x50, 0x21, 0x0E, 0x74, - 0x88, 0x2E, 0xF8, 0xE6, 0xF9, 0x08, 0xE6, 0x18, - 0xBE, 0x03, 0x02, 0x74, 0xFF, 0xFD, 0xED, 0x69, - 0x60, 0x09, 0x09, 0xE7, 0x19, 0x19, 0xF7, 0x09, - 0x09, 0x80, 0xF3, 0x16, 0x16, 0x80, 0xDA, 0xEE, - 0xD3, 0x9F, 0x40, 0x04, 0x05, 0x81, 0x05, 0x81, - 0xEE, 0xD3, 0x9F, 0x40, 0x22, 0x74, 0x88, 0x2E, - 0xF8, 0x08, 0xE6, 0xF9, 0xEE, 0xB5, 0x0C, 0x02, - 0xA9, 0x81, 0x18, 0x06, 0x06, 0xE6, 0xFD, 0xED, - 0x69, 0x60, 0x09, 0x19, 0x19, 0xE7, 0x09, 0x09, - 0xF7, 0x19, 0x80, 0xF3, 0x1E, 0x80, 0xD9, 0xEF, - 0x24, 0x88, 0xF8, 0xE6, 0x04, 0xF8, 0xEF, 0x2F, - 0x04, 0x90, 0x45, 0xDE, 0x93, 0xF6, 0x08, 0xEF, - 0x2F, 0x93, 0xF6, 0x7F, 0x00, 0x22, 0xEF, 0xD3, - 0x94, 0x03, 0x40, 0x03, 0x7F, 0xFF, 0x22, 0xEF, - 0x23, 0x24, 0x81, 0xF8, 0xE6, 0x30, 0xE5, 0xF4, - 0xC2, 0xAF, 0xE6, 0x54, 0x8C, 0xF6, 0xD2, 0xAF, - 0xE5, 0x0C, 0xB5, 0x07, 0x0A, 0x74, 0x88, 0x2F, - 0xF8, 0xE6, 0xF5, 0x81, 0x02, 0x42, 0x4D, 0x50, - 0x2E, 0x74, 0x89, 0x2F, 0xF8, 0xE6, 0xBF, 0x03, - 0x02, 0x74, 0xFF, 0xFD, 0x18, 0xE6, 0xF9, 0x74, - 0x88, 0x2F, 0xF8, 0xFB, 0xE6, 0xFC, 0xE9, 0x6C, - 0x60, 0x08, 0xA8, 0x05, 0xE7, 0xF6, 0x1D, 0x19, - 0x80, 0xF4, 0xA8, 0x03, 0xA6, 0x05, 0x1F, 0xE5, - 0x0C, 0xB5, 0x07, 0xE3, 0x7F, 0x00, 0x22, 0x74, - 0x89, 0x2F, 0xF8, 0xE6, 0xFD, 0x18, 0x86, 0x01, - 0x0F, 0x74, 0x88, 0x2F, 0xF8, 0xA6, 0x01, 0x08, - 0x86, 0x04, 0xE5, 0x0C, 0xB5, 0x07, 0x02, 0xAC, - 0x81, 0xED, 0x6C, 0x60, 0x08, 0x0D, 0x09, 0xA8, - 0x05, 0xE6, 0xF7, 0x80, 0xF4, 0xE5, 0x0C, 0xB5, - 0x07, 0xDE, 0x89, 0x81, 0x7F, 0x00, 0x22, 0xEF, - 0xD3, 0x94, 0x03, 0x40, 0x03, 0x7F, 0xFF, 0x22, - 0xEF, 0x23, 0x24, 0x81, 0xF8, 0xC2, 0xAF, 0xE6, - 0x30, 0xE5, 0x05, 0x30, 0xE0, 0x02, 0xD2, 0xE4, - 0xD2, 0xE2, 0xC6, 0xD2, 0xAF, 0x7F, 0x00, 0x30, - 0xE2, 0x01, 0x0F, 0x02, 0x42, 0x4C, 0x8F, 0xF0, - 0xE4, 0xFF, 0xFE, 0xE5, 0x0C, 0x23, 0x24, 0x80, - 0xF8, 0xC2, 0xA9, 0x30, 0xF7, 0x0D, 0x7F, 0x08, - 0xE6, 0x60, 0x0B, 0x2D, 0xF6, 0x60, 0x30, 0x50, - 0x2E, 0x80, 0x07, 0x30, 0xF1, 0x06, 0xED, 0xF6, - 0x60, 0x25, 0x7E, 0x02, 0x08, 0x30, 0xF0, 0x10, - 0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x23, 0x0E, 0x30, - 0xE2, 0x0C, 0xD2, 0xAF, 0x7F, 0x04, 0x80, 0x12, - 0xC2, 0xAF, 0xE6, 0x10, 0xE7, 0x13, 0x54, 0xEC, - 0x4E, 0xF6, 0xD2, 0xAF, 0x02, 0x42, 0x4D, 0x7F, - 0x08, 0x08, 0xEF, 0x44, 0x83, 0xF4, 0xC2, 0xAF, - 0x56, 0xC6, 0xD2, 0xAF, 0x54, 0x80, 0x4F, 0xFF, - 0x22, 0xC5, 0xF0, 0xF8, 0xA3, 0xE0, 0x28, 0xF0, - 0xC5, 0xF0, 0xF8, 0xE5, 0x82, 0x15, 0x82, 0x70, - 0x02, 0x15, 0x83, 0xE0, 0x38, 0xF0, 0x22, 0xEF, - 0x5B, 0xFF, 0xEE, 0x5A, 0xFE, 0xED, 0x59, 0xFD, - 0xEC, 0x58, 0xFC, 0x22, 0xEF, 0x4B, 0xFF, 0xEE, - 0x4A, 0xFE, 0xED, 0x49, 0xFD, 0xEC, 0x48, 0xFC, - 0x22, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xA3, 0xE0, - 0xFE, 0xA3, 0xE0, 0xFF, 0x22, 0xE2, 0xFC, 0x08, - 0xE2, 0xFD, 0x08, 0xE2, 0xFE, 0x08, 0xE2, 0xFF, - 0x22, 0xE2, 0xFB, 0x08, 0xE2, 0xF9, 0x08, 0xE2, - 0xFA, 0x08, 0xE2, 0xCB, 0xF8, 0x22, 0xEC, 0xF2, - 0x08, 0xED, 0xF2, 0x08, 0xEE, 0xF2, 0x08, 0xEF, - 0xF2, 0x22, 0xA4, 0x25, 0x82, 0xF5, 0x82, 0xE5, - 0xF0, 0x35, 0x83, 0xF5, 0x83, 0x22, 0xE0, 0xFB, - 0xA3, 0xE0, 0xFA, 0xA3, 0xE0, 0xF9, 0x22, 0xEB, - 0xF0, 0xA3, 0xEA, 0xF0, 0xA3, 0xE9, 0xF0, 0x22, - 0xD0, 0x83, 0xD0, 0x82, 0xF8, 0xE4, 0x93, 0x70, - 0x12, 0x74, 0x01, 0x93, 0x70, 0x0D, 0xA3, 0xA3, - 0x93, 0xF8, 0x74, 0x01, 0x93, 0xF5, 0x82, 0x88, - 0x83, 0xE4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, - 0xEF, 0xA3, 0xA3, 0xA3, 0x80, 0xDF, 0x02, 0x45, - 0x8C, 0x02, 0x42, 0xDD, 0xE4, 0x93, 0xA3, 0xF8, - 0xE4, 0x93, 0xA3, 0x40, 0x03, 0xF6, 0x80, 0x01, - 0xF2, 0x08, 0xDF, 0xF4, 0x80, 0x29, 0xE4, 0x93, - 0xA3, 0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, 0xC3, - 0x33, 0xC4, 0x54, 0x0F, 0x44, 0x20, 0xC8, 0x83, - 0x40, 0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, 0xF6, - 0xDF, 0xE4, 0x80, 0x0B, 0x01, 0x02, 0x04, 0x08, - 0x10, 0x20, 0x40, 0x80, 0x90, 0x45, 0xD1, 0xE4, - 0x7E, 0x01, 0x93, 0x60, 0xBC, 0xA3, 0xFF, 0x54, - 0x3F, 0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, 0xE4, - 0x93, 0xA3, 0x60, 0x01, 0x0E, 0xCF, 0x54, 0xC0, - 0x25, 0xE0, 0x60, 0xA8, 0x40, 0xB8, 0xE4, 0x93, - 0xA3, 0xFA, 0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, - 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCA, 0xC5, 0x83, - 0xCA, 0xF0, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCA, - 0xC5, 0x83, 0xCA, 0xDF, 0xE9, 0xDE, 0xE7, 0x80, - 0xBE, 0x00, 0x41, 0x82, 0x09, 0x00, 0x41, 0x82, - 0x0A, 0x00, 0x41, 0x82, 0x17, 0x00, 0x59, 0xE2, - 0x5C, 0x24, 0x5E, 0x5D, 0x5F, 0xA1, 0xC0, 0xE0, - 0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, 0xD0, - 0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, 0xC0, - 0x02, 0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05, 0xC0, - 0x06, 0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74, 0xE6, - 0xF0, 0x74, 0x45, 0xA3, 0xF0, 0xD1, 0x35, 0x74, - 0xE6, 0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x45, - 0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06, 0xD0, 0x05, - 0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, - 0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83, - 0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0x90, 0x00, 0x54, - 0xE0, 0x55, 0x35, 0xF5, 0x39, 0xA3, 0xE0, 0x55, - 0x36, 0xF5, 0x3A, 0xA3, 0xE0, 0x55, 0x37, 0xF5, - 0x3B, 0xA3, 0xE0, 0x55, 0x38, 0xF5, 0x3C, 0xAD, - 0x39, 0x7F, 0x54, 0x12, 0x32, 0x1E, 0xAD, 0x3A, - 0x7F, 0x55, 0x12, 0x32, 0x1E, 0xAD, 0x3B, 0x7F, - 0x56, 0x12, 0x32, 0x1E, 0xAD, 0x3C, 0x7F, 0x57, - 0x12, 0x32, 0x1E, 0x53, 0x91, 0xEF, 0x22, 0xC0, - 0xE0, 0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, - 0xD0, 0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, - 0xC0, 0x02, 0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05, - 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74, - 0x6F, 0xF0, 0x74, 0x46, 0xA3, 0xF0, 0x12, 0x6C, - 0x78, 0xE5, 0x41, 0x30, 0xE4, 0x04, 0x7F, 0x02, - 0x91, 0x27, 0xE5, 0x41, 0x30, 0xE6, 0x03, 0x12, - 0x6C, 0xD5, 0xE5, 0x43, 0x30, 0xE0, 0x03, 0x12, - 0x51, 0xC2, 0xE5, 0x43, 0x30, 0xE1, 0x03, 0x12, - 0x4D, 0x0C, 0xE5, 0x43, 0x30, 0xE2, 0x03, 0x12, - 0x4C, 0xC1, 0xE5, 0x43, 0x30, 0xE3, 0x03, 0x12, - 0x6C, 0xE2, 0xE5, 0x43, 0x30, 0xE4, 0x03, 0x12, - 0x6D, 0x04, 0xE5, 0x43, 0x30, 0xE5, 0x03, 0x12, - 0x6D, 0x33, 0xE5, 0x43, 0x30, 0xE6, 0x02, 0xF1, - 0x0F, 0xE5, 0x44, 0x30, 0xE1, 0x03, 0x12, 0x51, - 0x7F, 0x74, 0x6F, 0x04, 0x90, 0x01, 0xC4, 0xF0, - 0x74, 0x46, 0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06, - 0xD0, 0x05, 0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02, - 0xD0, 0x01, 0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, - 0xD0, 0x83, 0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0x90, - 0x80, 0xDE, 0xE0, 0xB4, 0x01, 0x13, 0x90, 0x81, - 0x27, 0xE0, 0x60, 0x0D, 0x90, 0x81, 0x2B, 0xE0, - 0x54, 0xFE, 0xF0, 0x54, 0x07, 0x70, 0x02, 0xF1, - 0x2A, 0x22, 0x90, 0x81, 0x1F, 0xE0, 0x90, 0x81, - 0x29, 0x30, 0xE0, 0x05, 0xE0, 0xFF, 0x02, 0x74, - 0x8F, 0xE0, 0xFF, 0x7D, 0x01, 0xD3, 0x10, 0xAF, - 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, 0x13, 0xED, - 0xF0, 0x90, 0x81, 0x2A, 0xE0, 0x90, 0x82, 0x14, - 0xF0, 0x90, 0x81, 0x24, 0xE0, 0xFE, 0xC4, 0x13, - 0x13, 0x54, 0x03, 0x30, 0xE0, 0x03, 0x02, 0x48, - 0xA0, 0xEE, 0xC4, 0x13, 0x13, 0x13, 0x54, 0x01, - 0x30, 0xE0, 0x03, 0x02, 0x48, 0xA0, 0x90, 0x82, - 0x14, 0xE0, 0xFE, 0x6F, 0x70, 0x03, 0x02, 0x48, - 0xA0, 0xEF, 0x70, 0x03, 0x02, 0x48, 0x17, 0x24, - 0xFE, 0x70, 0x03, 0x02, 0x48, 0x50, 0x24, 0xFE, - 0x60, 0x51, 0x24, 0xFC, 0x70, 0x03, 0x02, 0x48, - 0x8B, 0x24, 0xFC, 0x60, 0x03, 0x02, 0x48, 0xA0, - 0xEE, 0xB4, 0x0E, 0x03, 0x12, 0x49, 0x5E, 0x90, - 0x82, 0x14, 0xE0, 0x70, 0x05, 0x7F, 0x01, 0x12, - 0x49, 0x93, 0x90, 0x82, 0x14, 0xE0, 0xB4, 0x06, - 0x03, 0x12, 0x49, 0x34, 0x90, 0x82, 0x14, 0xE0, - 0xB4, 0x04, 0x0F, 0x90, 0x82, 0x13, 0xE0, 0xFF, - 0x60, 0x05, 0x12, 0x73, 0x75, 0x80, 0x03, 0x12, - 0x66, 0x26, 0x90, 0x82, 0x14, 0xE0, 0x64, 0x08, - 0x60, 0x03, 0x02, 0x48, 0xA0, 0x12, 0x73, 0xD3, - 0x02, 0x48, 0xA0, 0x90, 0x82, 0x14, 0xE0, 0x70, - 0x05, 0x7F, 0x01, 0x12, 0x49, 0x93, 0x90, 0x82, - 0x14, 0xE0, 0xB4, 0x06, 0x03, 0x12, 0x49, 0x34, - 0x90, 0x82, 0x14, 0xE0, 0xB4, 0x0E, 0x09, 0x12, - 0x48, 0xA5, 0xBF, 0x01, 0x03, 0x12, 0x49, 0x5E, - 0x90, 0x82, 0x14, 0xE0, 0x64, 0x0C, 0x60, 0x02, - 0x01, 0xA0, 0x11, 0xA5, 0xEF, 0x64, 0x01, 0x60, - 0x02, 0x01, 0xA0, 0x11, 0xFA, 0x01, 0xA0, 0x90, - 0x82, 0x14, 0xE0, 0xB4, 0x0E, 0x07, 0x11, 0xA5, - 0xBF, 0x01, 0x02, 0x31, 0x5E, 0x90, 0x82, 0x14, - 0xE0, 0xB4, 0x06, 0x02, 0x31, 0x34, 0x90, 0x82, - 0x14, 0xE0, 0xB4, 0x0C, 0x07, 0x11, 0xA5, 0xBF, - 0x01, 0x02, 0x11, 0xFA, 0x90, 0x82, 0x14, 0xE0, - 0x64, 0x04, 0x70, 0x5C, 0x12, 0x72, 0xF5, 0xEF, - 0x64, 0x01, 0x70, 0x54, 0x31, 0xBE, 0x80, 0x50, - 0x90, 0x82, 0x14, 0xE0, 0xB4, 0x0E, 0x07, 0x11, - 0xA5, 0xBF, 0x01, 0x02, 0x31, 0x5E, 0x90, 0x82, - 0x14, 0xE0, 0xB4, 0x06, 0x02, 0x31, 0x34, 0x90, - 0x82, 0x14, 0xE0, 0xB4, 0x0C, 0x07, 0x11, 0xA5, - 0xBF, 0x01, 0x02, 0x11, 0xFA, 0x90, 0x82, 0x14, - 0xE0, 0x70, 0x04, 0x7F, 0x01, 0x31, 0x93, 0x90, - 0x82, 0x14, 0xE0, 0xB4, 0x04, 0x1A, 0x12, 0x73, - 0xBB, 0x80, 0x15, 0x90, 0x82, 0x14, 0xE0, 0xB4, - 0x0C, 0x0E, 0x90, 0x81, 0x25, 0xE0, 0xFF, 0x13, - 0x13, 0x54, 0x3F, 0x30, 0xE0, 0x02, 0x31, 0xB1, - 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD1, 0xAB, 0xEF, - 0x64, 0x01, 0x60, 0x08, 0x90, 0x01, 0xB8, 0x74, - 0x01, 0xF0, 0x80, 0x3D, 0x90, 0x81, 0x24, 0xE0, - 0xFF, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x30, 0xE0, - 0x08, 0x90, 0x01, 0xB8, 0x74, 0x02, 0xF0, 0x80, - 0x28, 0xEF, 0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x08, - 0x90, 0x01, 0xB8, 0x74, 0x04, 0xF0, 0x80, 0x19, - 0x90, 0x81, 0x29, 0xE0, 0xD3, 0x94, 0x04, 0x40, - 0x08, 0x90, 0x01, 0xB8, 0x74, 0x08, 0xF0, 0x80, - 0x08, 0x90, 0x01, 0xB8, 0xE4, 0xF0, 0x7F, 0x01, - 0x22, 0x90, 0x01, 0xB9, 0x74, 0x02, 0xF0, 0x7F, - 0x00, 0x22, 0x90, 0x80, 0xDE, 0xE0, 0x64, 0x01, - 0x70, 0x31, 0x90, 0x81, 0x25, 0xE0, 0x54, 0xFD, - 0xF0, 0x90, 0x05, 0x22, 0x74, 0x6F, 0xF0, 0x7F, - 0x01, 0xF1, 0x0D, 0xBF, 0x01, 0x12, 0x90, 0x81, - 0x24, 0xE0, 0x44, 0x80, 0xF0, 0x90, 0x81, 0x2A, - 0x74, 0x0E, 0xF0, 0x90, 0x81, 0x23, 0xF0, 0x22, - 0x90, 0x01, 0xB9, 0x74, 0x01, 0xF0, 0x90, 0x01, - 0xB8, 0x04, 0xF0, 0x22, 0x90, 0x81, 0x25, 0xE0, - 0x90, 0x06, 0x04, 0x20, 0xE0, 0x0C, 0xE0, 0x44, - 0x40, 0xF0, 0x90, 0x81, 0x2A, 0x74, 0x04, 0xF0, - 0x80, 0x0E, 0xE0, 0x54, 0x7F, 0xF0, 0x90, 0x81, - 0x2A, 0x74, 0x0C, 0xF0, 0x90, 0x81, 0x23, 0xF0, - 0x90, 0x05, 0x22, 0xE4, 0xF0, 0x22, 0x90, 0x81, - 0x25, 0xE0, 0xC3, 0x13, 0x20, 0xE0, 0x08, 0x90, - 0x81, 0x2A, 0x74, 0x0C, 0xF0, 0x80, 0x1E, 0x90, - 0x06, 0x04, 0xE0, 0x44, 0x40, 0xF0, 0xE0, 0x44, - 0x80, 0xF0, 0x90, 0x81, 0x2A, 0x74, 0x04, 0xF0, - 0x90, 0x05, 0x27, 0xE0, 0x44, 0x80, 0xF0, 0x90, - 0x81, 0x23, 0x74, 0x04, 0xF0, 0x90, 0x05, 0x22, - 0xE4, 0xF0, 0x22, 0x90, 0x82, 0x15, 0xEF, 0xF0, - 0x12, 0x54, 0x65, 0x90, 0x82, 0x15, 0xE0, 0x60, - 0x05, 0x90, 0x05, 0x22, 0xE4, 0xF0, 0x90, 0x81, - 0x2A, 0x74, 0x04, 0xF0, 0x90, 0x81, 0x23, 0xF0, - 0x22, 0x31, 0xE3, 0x90, 0x81, 0x2A, 0x74, 0x08, - 0xF0, 0x90, 0x81, 0x23, 0xF0, 0x22, 0x90, 0x05, - 0x22, 0x74, 0xFF, 0xF0, 0xF1, 0x3A, 0x90, 0x01, - 0x37, 0x74, 0x02, 0xF0, 0xFD, 0x7F, 0x03, 0x51, - 0x57, 0x31, 0xE3, 0xE4, 0x90, 0x81, 0x2A, 0xF0, - 0x90, 0x81, 0x23, 0xF0, 0x22, 0x90, 0x05, 0x22, - 0x74, 0xFF, 0xF0, 0xF1, 0x3A, 0x90, 0x85, 0xBB, - 0x12, 0x20, 0xDA, 0xCC, 0xF0, 0x00, 0xC0, 0x7F, - 0x8C, 0x7E, 0x08, 0x12, 0x2E, 0xA2, 0x90, 0x85, - 0xBB, 0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, 0x14, - 0x7F, 0x70, 0x7E, 0x0E, 0x12, 0x2E, 0xA2, 0x90, - 0x81, 0xF9, 0x12, 0x20, 0xDA, 0x00, 0x00, 0x00, - 0x00, 0xE4, 0xFD, 0xFF, 0x12, 0x55, 0x1C, 0x7F, - 0x7C, 0x7E, 0x08, 0x12, 0x2D, 0x5C, 0xEC, 0x44, - 0x80, 0xFC, 0x90, 0x82, 0x05, 0x12, 0x20, 0xCE, - 0x90, 0x82, 0x05, 0x12, 0x44, 0xD9, 0x90, 0x85, - 0xBB, 0x12, 0x20, 0xCE, 0x7F, 0x7C, 0x7E, 0x08, - 0x12, 0x2E, 0xA2, 0x90, 0x01, 0x00, 0x74, 0x3F, - 0xF0, 0xA3, 0xE0, 0x54, 0xFD, 0xF0, 0x90, 0x05, - 0x53, 0xE0, 0x44, 0x20, 0xF0, 0x22, 0x90, 0x01, - 0x34, 0x74, 0x40, 0xF0, 0xFD, 0xE4, 0xFF, 0x74, - 0x3D, 0x2F, 0xF8, 0xE6, 0x4D, 0xFE, 0xF6, 0x74, - 0x30, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x01, 0xF5, - 0x83, 0xEE, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, - 0xC3, 0xC0, 0xD0, 0xE4, 0x90, 0x81, 0xCB, 0xF0, - 0x12, 0x1F, 0xA4, 0xFF, 0x54, 0x01, 0xFE, 0x90, - 0x81, 0x1F, 0xE0, 0x54, 0xFE, 0x4E, 0xFE, 0xF0, - 0xEF, 0x54, 0x02, 0xFF, 0xEE, 0x54, 0xFD, 0x4F, - 0xFF, 0xF0, 0x12, 0x1F, 0xA4, 0xFE, 0x54, 0x04, - 0xFD, 0xEF, 0x54, 0xFB, 0x4D, 0xFF, 0x90, 0x81, - 0x1F, 0xF0, 0xEE, 0x54, 0x08, 0xFE, 0xEF, 0x54, - 0xF7, 0x4E, 0xFF, 0xF0, 0x12, 0x1F, 0xA4, 0xFE, - 0x54, 0x10, 0xFD, 0xEF, 0x54, 0xEF, 0x4D, 0xFF, - 0x90, 0x81, 0x1F, 0xF0, 0xEE, 0x54, 0x20, 0xFE, - 0xEF, 0x54, 0xDF, 0x4E, 0xF0, 0x12, 0x1F, 0xA4, - 0xC3, 0x13, 0x20, 0xE0, 0x02, 0x61, 0x5E, 0x90, - 0x81, 0x1F, 0xE0, 0xFF, 0x30, 0xE0, 0x6D, 0x90, - 0x81, 0xCB, 0x74, 0x21, 0xF0, 0xEF, 0x13, 0x13, - 0x54, 0x3F, 0x30, 0xE0, 0x0B, 0x51, 0x4E, 0x90, - 0x81, 0xCB, 0xE0, 0x44, 0x08, 0xF0, 0x80, 0x0C, - 0xE4, 0x90, 0x81, 0x20, 0xF0, 0xA3, 0xF0, 0x7D, - 0x40, 0xFF, 0x91, 0x26, 0x90, 0x81, 0x1F, 0xE0, - 0xFD, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x30, 0xE0, - 0x07, 0x90, 0x81, 0xCB, 0xE0, 0x44, 0x12, 0xF0, - 0xED, 0xC4, 0x54, 0x0F, 0x30, 0xE0, 0x07, 0x90, - 0x81, 0xCB, 0xE0, 0x44, 0x14, 0xF0, 0x90, 0x81, - 0x1F, 0xE0, 0xC4, 0x13, 0x54, 0x07, 0x30, 0xE0, - 0x07, 0x90, 0x81, 0xCB, 0xE0, 0x44, 0x80, 0xF0, - 0x90, 0x81, 0xCB, 0xE0, 0x90, 0x05, 0x27, 0xF0, - 0x90, 0x81, 0x22, 0xE0, 0x60, 0x02, 0x81, 0x17, - 0x7F, 0x01, 0x80, 0x15, 0x90, 0x81, 0xCB, 0x74, - 0x01, 0xF0, 0x90, 0x05, 0x27, 0xF0, 0x90, 0x81, - 0x22, 0xE0, 0x64, 0x04, 0x60, 0x02, 0x81, 0x17, - 0xFF, 0x12, 0x53, 0x0E, 0x81, 0x17, 0x90, 0x81, - 0x1F, 0xE0, 0xFF, 0x20, 0xE0, 0x02, 0x61, 0xE7, - 0x90, 0x81, 0xCB, 0x74, 0x31, 0xF0, 0xEF, 0x13, - 0x13, 0x54, 0x3F, 0x30, 0xE0, 0x0B, 0x51, 0x4E, - 0x90, 0x81, 0xCB, 0xE0, 0x44, 0x08, 0xF0, 0x80, - 0x06, 0x7D, 0x40, 0xE4, 0xFF, 0x91, 0x26, 0x90, - 0x81, 0x1F, 0xE0, 0xFD, 0x13, 0x13, 0x13, 0x54, - 0x1F, 0x30, 0xE0, 0x07, 0x90, 0x81, 0xCB, 0xE0, - 0x44, 0x02, 0xF0, 0xED, 0xC4, 0x54, 0x0F, 0x30, - 0xE0, 0x07, 0x90, 0x81, 0xCB, 0xE0, 0x44, 0x04, - 0xF0, 0x90, 0x81, 0xCB, 0xE0, 0x90, 0x05, 0x27, - 0xF0, 0x90, 0x81, 0x23, 0xE0, 0x64, 0x02, 0x70, - 0x1D, 0xFD, 0x7F, 0x04, 0x12, 0x47, 0x3D, 0x12, - 0x51, 0x73, 0xBF, 0x01, 0x09, 0x90, 0x81, 0x29, - 0xE0, 0xFF, 0x7D, 0x01, 0x80, 0x03, 0xE4, 0xFD, - 0xFF, 0x12, 0x47, 0x3D, 0x80, 0x41, 0x90, 0x81, - 0x2A, 0xE0, 0x90, 0x81, 0x23, 0xF0, 0x90, 0x05, - 0x27, 0xE0, 0x44, 0x40, 0xF0, 0x80, 0x30, 0x90, - 0x81, 0xCB, 0x74, 0x01, 0xF0, 0x90, 0x05, 0x27, - 0xF0, 0x90, 0x81, 0x23, 0xE0, 0xB4, 0x02, 0x06, - 0x7D, 0x01, 0x7F, 0x04, 0x80, 0x0B, 0x90, 0x81, - 0x23, 0xE0, 0xB4, 0x08, 0x07, 0x7D, 0x01, 0x7F, - 0x0C, 0x12, 0x47, 0x3D, 0xD1, 0x34, 0x90, 0x81, - 0x29, 0x12, 0x47, 0x39, 0x12, 0x5A, 0xA7, 0xD0, - 0xD0, 0x92, 0xAF, 0x22, 0x7D, 0x02, 0x7F, 0x02, - 0x91, 0x26, 0x7D, 0x01, 0x7F, 0x02, 0x74, 0x3D, - 0x2F, 0xF8, 0xE6, 0xFE, 0xED, 0xF4, 0x5E, 0xFE, - 0xF6, 0x74, 0x30, 0x2F, 0xF5, 0x82, 0xE4, 0x34, - 0x01, 0xF5, 0x83, 0xEE, 0xF0, 0x22, 0xEF, 0x70, - 0x37, 0x7D, 0x78, 0x7F, 0x02, 0x91, 0x26, 0x7D, - 0x02, 0x7F, 0x03, 0x91, 0x26, 0x7D, 0xC8, 0x7F, - 0x02, 0x12, 0x71, 0x8F, 0x90, 0x01, 0x57, 0xE4, - 0xF0, 0x90, 0x01, 0x3C, 0x74, 0x02, 0xF0, 0x7D, - 0x01, 0x7F, 0x0C, 0x12, 0x47, 0x3D, 0x90, 0x81, - 0x24, 0xE0, 0x54, 0xF7, 0xF0, 0x54, 0xEF, 0xF0, - 0x90, 0x06, 0x0A, 0xE0, 0x54, 0xF8, 0xF0, 0x22, - 0x90, 0x01, 0x36, 0x74, 0x78, 0xF0, 0xA3, 0x74, - 0x02, 0xF0, 0x7D, 0x78, 0xFF, 0x51, 0x57, 0x7D, - 0x02, 0x7F, 0x03, 0x51, 0x57, 0x90, 0x06, 0x0A, - 0xE0, 0x44, 0x07, 0xF0, 0x90, 0x81, 0x32, 0xA3, - 0xE0, 0x90, 0x05, 0x58, 0xF0, 0x90, 0x80, 0xDE, - 0xE0, 0xB4, 0x01, 0x15, 0x90, 0x81, 0x25, 0xE0, - 0x54, 0xFB, 0xF0, 0x90, 0x81, 0x2A, 0xE0, 0x20, - 0xE2, 0x0E, 0x7D, 0x01, 0x7F, 0x04, 0x02, 0x47, - 0x3D, 0x90, 0x81, 0x25, 0xE0, 0x44, 0x04, 0xF0, - 0x22, 0x90, 0x81, 0x1F, 0xE0, 0xFF, 0x30, 0xE0, - 0x08, 0x90, 0x81, 0x23, 0xE0, 0x64, 0x02, 0x60, - 0x3A, 0x90, 0x81, 0x27, 0xE0, 0x70, 0x04, 0xEF, - 0x30, 0xE0, 0x0A, 0x90, 0x81, 0x2A, 0xE0, 0x64, - 0x02, 0x60, 0x28, 0xB1, 0x83, 0x90, 0x81, 0x25, - 0xE0, 0x13, 0x13, 0x13, 0x54, 0x1F, 0x30, 0xE0, - 0x14, 0x90, 0x81, 0x2D, 0xE0, 0xFF, 0xA3, 0xE0, - 0x6F, 0x70, 0x0A, 0xF1, 0xCD, 0x91, 0x1C, 0x90, - 0x81, 0x2E, 0xE0, 0x14, 0xF0, 0x90, 0x01, 0xE6, - 0xE0, 0x04, 0xF0, 0x22, 0x90, 0x81, 0x1F, 0xE0, - 0x30, 0xE0, 0x06, 0x90, 0x81, 0x21, 0x74, 0x01, - 0xF0, 0x90, 0x81, 0x27, 0xE0, 0x60, 0x45, 0x90, - 0x81, 0x25, 0xE0, 0xFF, 0x13, 0x13, 0x13, 0x54, - 0x1F, 0x30, 0xE0, 0x12, 0x90, 0x01, 0x3B, 0xE0, - 0x30, 0xE4, 0x0B, 0x91, 0x1C, 0x90, 0x81, 0x2D, - 0xE0, 0x14, 0x90, 0x05, 0x73, 0xF0, 0x90, 0x82, - 0x0B, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x44, 0xA9, - 0xC3, 0x90, 0x82, 0x0C, 0xE0, 0x94, 0x80, 0x90, - 0x82, 0x0B, 0xE0, 0x64, 0x80, 0x94, 0x80, 0x40, - 0x0B, 0x90, 0x01, 0x98, 0xE0, 0x54, 0xFE, 0xF0, - 0xE0, 0x44, 0x01, 0xF0, 0x12, 0x75, 0xF8, 0xD1, - 0xD6, 0x90, 0x81, 0x3F, 0xE0, 0x30, 0xE0, 0x0C, - 0xE4, 0xF5, 0x1D, 0xA3, 0xF1, 0xFB, 0x90, 0x01, - 0x57, 0x74, 0x05, 0xF0, 0x90, 0x01, 0xBE, 0xE0, - 0x04, 0xF0, 0x22, 0x90, 0x80, 0xDE, 0xE0, 0x64, - 0x01, 0x60, 0x02, 0xC1, 0x23, 0x90, 0x81, 0x27, - 0xE0, 0x70, 0x02, 0xC1, 0x23, 0x90, 0x81, 0x26, - 0xE0, 0xC4, 0x54, 0x0F, 0x64, 0x01, 0x70, 0x22, - 0x90, 0x06, 0xAB, 0xE0, 0x90, 0x81, 0x2E, 0xF0, - 0x90, 0x06, 0xAA, 0xE0, 0x90, 0x81, 0x2D, 0xF0, - 0xA3, 0xE0, 0xFF, 0x70, 0x08, 0x90, 0x81, 0x2D, - 0xE0, 0xFE, 0xFF, 0x80, 0x00, 0x90, 0x81, 0x2E, - 0xEF, 0xF0, 0x90, 0x81, 0x25, 0xE0, 0x44, 0x04, - 0xF0, 0xE4, 0x90, 0x81, 0x30, 0xF0, 0x90, 0x81, - 0x32, 0xA3, 0xE0, 0x90, 0x05, 0x58, 0xF0, 0x90, - 0x01, 0x57, 0xE4, 0xF0, 0x90, 0x01, 0x3C, 0x74, - 0x02, 0xF0, 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFD, - 0xF0, 0x54, 0xEF, 0xF0, 0x90, 0x81, 0x26, 0xE0, - 0xFF, 0xC4, 0x54, 0x0F, 0x24, 0xFD, 0x50, 0x02, - 0x80, 0x0F, 0x90, 0x81, 0x1F, 0xE0, 0x30, 0xE0, - 0x05, 0x12, 0x6D, 0xF2, 0x80, 0x03, 0x12, 0x6E, - 0xC9, 0x90, 0x81, 0x25, 0xE0, 0x13, 0x13, 0x13, - 0x54, 0x1F, 0x30, 0xE0, 0x0E, 0x90, 0x81, 0x2D, - 0xE0, 0xFF, 0xA3, 0xE0, 0xB5, 0x07, 0x04, 0xF1, - 0xCD, 0x91, 0x22, 0x90, 0x81, 0x1F, 0xE0, 0xC3, - 0x13, 0x20, 0xE0, 0x07, 0x90, 0x81, 0x25, 0xE0, - 0x44, 0x04, 0xF0, 0x22, 0xD1, 0xAB, 0xEF, 0x70, - 0x02, 0xD1, 0x3C, 0x22, 0x90, 0x81, 0x27, 0xE0, - 0x64, 0x01, 0x70, 0x66, 0x90, 0x81, 0x26, 0xE0, - 0x54, 0x0F, 0x60, 0x51, 0x90, 0x81, 0x2A, 0xE0, - 0x70, 0x03, 0xFF, 0x31, 0x93, 0x90, 0x81, 0x2A, - 0xE0, 0x64, 0x0C, 0x60, 0x03, 0x12, 0x66, 0x26, - 0x90, 0x01, 0x5B, 0xE4, 0xF0, 0x90, 0x01, 0x3C, - 0x74, 0x04, 0xF0, 0xD1, 0xAB, 0xEF, 0x64, 0x01, - 0x60, 0x38, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x3A, - 0xE0, 0xC3, 0x13, 0x54, 0x7F, 0xF5, 0x1E, 0xE4, - 0xFB, 0xFD, 0x7F, 0x58, 0x7E, 0x01, 0x12, 0x50, - 0x05, 0x90, 0x01, 0x5B, 0x74, 0x05, 0xF0, 0x90, - 0x06, 0x92, 0x74, 0x01, 0xF0, 0x90, 0x81, 0x24, - 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x81, 0x2A, - 0xE0, 0x70, 0x07, 0x7D, 0x01, 0x7F, 0x04, 0x12, - 0x47, 0x3D, 0x22, 0x90, 0x04, 0x1A, 0xE0, 0xF4, - 0x60, 0x03, 0x7F, 0x00, 0x22, 0x90, 0x04, 0x1B, - 0xE0, 0x54, 0x07, 0x64, 0x07, 0x7F, 0x01, 0x60, - 0x02, 0x7F, 0x00, 0x22, 0x12, 0x50, 0x60, 0x90, - 0x81, 0x2D, 0xE0, 0x14, 0x90, 0x05, 0x73, 0xF0, - 0x7D, 0x02, 0x7F, 0x02, 0x51, 0x57, 0x90, 0x81, - 0x42, 0xE0, 0x30, 0xE0, 0x2D, 0x90, 0x80, 0xDE, - 0xE0, 0xB4, 0x01, 0x26, 0x90, 0x82, 0x17, 0xE0, - 0x04, 0xF0, 0xE0, 0xB4, 0x0A, 0x0B, 0x90, 0x81, - 0x44, 0xE0, 0x04, 0xF0, 0xE4, 0x90, 0x82, 0x17, - 0xF0, 0x90, 0x81, 0x44, 0xE0, 0xFF, 0x90, 0x81, - 0x43, 0xE0, 0xB5, 0x07, 0x05, 0xE4, 0xA3, 0xF0, - 0xF1, 0x0B, 0x22, 0xE4, 0xFF, 0x8F, 0x53, 0x90, - 0x04, 0x1D, 0xE0, 0x60, 0x19, 0x90, 0x05, 0x22, - 0xE0, 0xF5, 0x56, 0x74, 0xFF, 0xF0, 0xF1, 0x3A, - 0xBF, 0x01, 0x03, 0x12, 0x74, 0xFB, 0x90, 0x05, - 0x22, 0xE5, 0x56, 0xF0, 0x80, 0x03, 0x12, 0x74, - 0xFB, 0x90, 0x04, 0x1F, 0x74, 0x20, 0xF0, 0x7F, - 0x01, 0x22, 0xE4, 0x90, 0x82, 0x0F, 0xF0, 0xA3, - 0xF0, 0x90, 0x05, 0xF8, 0xE0, 0x70, 0x0F, 0xA3, - 0xE0, 0x70, 0x0B, 0xA3, 0xE0, 0x70, 0x07, 0xA3, - 0xE0, 0x70, 0x03, 0x7F, 0x01, 0x22, 0xD3, 0x90, - 0x82, 0x10, 0xE0, 0x94, 0xE8, 0x90, 0x82, 0x0F, - 0xE0, 0x94, 0x03, 0x40, 0x0A, 0x90, 0x01, 0xC0, - 0xE0, 0x44, 0x20, 0xF0, 0x7F, 0x00, 0x22, 0x7F, - 0x32, 0x7E, 0x00, 0x12, 0x32, 0xAA, 0x90, 0x82, - 0x0F, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x44, 0xA9, - 0x80, 0xBF, 0x74, 0x1F, 0x2D, 0xF5, 0x82, 0xE4, - 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x54, 0x3F, 0xF0, - 0xEF, 0x60, 0x1D, 0x74, 0x21, 0x2D, 0xF5, 0x82, - 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x10, - 0xF0, 0x74, 0x1F, 0x2D, 0xF5, 0x82, 0xE4, 0x34, - 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0x22, - 0x74, 0x21, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0xFC, - 0xF5, 0x83, 0xE0, 0x54, 0xEF, 0xF0, 0x74, 0x1F, - 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, - 0xE0, 0x44, 0x40, 0xF0, 0x22, 0xEF, 0x14, 0x90, - 0x05, 0x73, 0xF0, 0x90, 0x01, 0x3F, 0x74, 0x10, - 0xF0, 0xFD, 0x7F, 0x03, 0x74, 0x45, 0x2F, 0xF8, - 0xE6, 0x4D, 0xFE, 0xF6, 0x74, 0x38, 0x2F, 0xF5, - 0x82, 0xE4, 0x34, 0x01, 0xF5, 0x83, 0xEE, 0xF0, - 0x22, 0xE0, 0x44, 0x02, 0xF0, 0xE4, 0xF5, 0x1D, - 0x90, 0x81, 0x39, 0xE0, 0xF5, 0x1E, 0xE4, 0xFB, - 0xFD, 0x7F, 0x54, 0x7E, 0x01, 0x8E, 0x19, 0x8F, - 0x1A, 0xE5, 0x1E, 0x54, 0x07, 0xC4, 0x33, 0x54, - 0xE0, 0x85, 0x19, 0x83, 0x85, 0x1A, 0x82, 0xF0, - 0xE5, 0x1D, 0x54, 0x07, 0xC4, 0x33, 0x54, 0xE0, - 0xFF, 0xE5, 0x1E, 0x13, 0x13, 0x13, 0x54, 0x1F, - 0x4F, 0xA3, 0xF0, 0xEB, 0x54, 0x07, 0xC4, 0x33, - 0x54, 0xE0, 0xFF, 0xE5, 0x1D, 0x13, 0x13, 0x13, - 0x54, 0x1F, 0x4F, 0x85, 0x1A, 0x82, 0x85, 0x19, - 0x83, 0xA3, 0xA3, 0xF0, 0xBD, 0x01, 0x0C, 0x85, - 0x1A, 0x82, 0x8E, 0x83, 0xA3, 0xA3, 0xA3, 0x74, - 0x03, 0xF0, 0x22, 0x85, 0x1A, 0x82, 0x85, 0x19, - 0x83, 0xA3, 0xA3, 0xA3, 0x74, 0x01, 0xF0, 0x22, - 0xE4, 0x90, 0x81, 0x4D, 0xF0, 0x90, 0x81, 0x27, - 0xE0, 0x60, 0x58, 0x90, 0x80, 0xDE, 0xE0, 0x64, - 0x01, 0x70, 0x50, 0x90, 0x81, 0x4D, 0x04, 0xF0, - 0xE4, 0x90, 0x81, 0x2E, 0xF0, 0x90, 0x81, 0x1F, - 0xE0, 0x30, 0xE0, 0x15, 0x90, 0x81, 0x23, 0xE0, - 0xB4, 0x02, 0x05, 0xE4, 0x90, 0x81, 0x4D, 0xF0, - 0x31, 0x73, 0xEF, 0x70, 0x04, 0x90, 0x81, 0x4D, - 0xF0, 0x90, 0x81, 0x4D, 0xE0, 0x60, 0x24, 0x90, - 0x81, 0x2B, 0xE0, 0x44, 0x10, 0xF0, 0xE4, 0xF5, - 0x1D, 0x90, 0x81, 0x2F, 0x12, 0x4F, 0xFB, 0x90, - 0x01, 0x57, 0x74, 0x05, 0xF0, 0x90, 0x81, 0x2A, - 0xE0, 0x20, 0xE2, 0x07, 0x7D, 0x01, 0x7F, 0x04, - 0x12, 0x47, 0x3D, 0x22, 0xE4, 0x90, 0x81, 0x4C, - 0xF0, 0x90, 0x81, 0x27, 0xE0, 0x70, 0x02, 0x21, - 0x72, 0x90, 0x80, 0xDE, 0xE0, 0x64, 0x01, 0x60, - 0x02, 0x21, 0x72, 0x90, 0x81, 0x26, 0xE0, 0xFF, - 0xC4, 0x54, 0x0F, 0x60, 0x22, 0x24, 0xFE, 0x60, - 0x03, 0x04, 0x70, 0x21, 0x90, 0x81, 0x2E, 0xE0, - 0x14, 0xF0, 0xE0, 0xFF, 0x60, 0x06, 0x90, 0x81, - 0x30, 0xE0, 0x60, 0x11, 0xEF, 0x70, 0x08, 0x90, - 0x81, 0x2D, 0xE0, 0xA3, 0xF0, 0x80, 0x00, 0x90, - 0x81, 0x4C, 0x74, 0x01, 0xF0, 0x90, 0x81, 0x1F, - 0xE0, 0x30, 0xE0, 0x15, 0x90, 0x81, 0x23, 0xE0, - 0xB4, 0x02, 0x05, 0xE4, 0x90, 0x81, 0x4C, 0xF0, - 0x31, 0x73, 0xEF, 0x70, 0x04, 0x90, 0x81, 0x4C, - 0xF0, 0x90, 0x81, 0x4C, 0xE0, 0x60, 0x43, 0x90, - 0x81, 0x2B, 0xE0, 0x44, 0x10, 0xF0, 0x90, 0x81, - 0x30, 0xE0, 0x60, 0x03, 0xB4, 0x01, 0x09, 0xE4, - 0xF5, 0x1D, 0x90, 0x81, 0x30, 0xE0, 0x80, 0x0D, - 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x30, 0xE0, 0x75, - 0xF0, 0x03, 0xA4, 0x24, 0xFE, 0xFF, 0x90, 0x81, - 0x2F, 0xE0, 0x2F, 0x12, 0x4F, 0xFC, 0x90, 0x01, - 0x57, 0x74, 0x05, 0xF0, 0x90, 0x81, 0x2A, 0xE0, - 0x20, 0xE2, 0x07, 0x7D, 0x01, 0x7F, 0x04, 0x12, - 0x47, 0x3D, 0x22, 0x90, 0x05, 0x43, 0xE0, 0x7F, - 0x00, 0x30, 0xE7, 0x02, 0x7F, 0x01, 0x22, 0x90, - 0x81, 0x27, 0xE0, 0x70, 0x07, 0x90, 0x81, 0x1F, - 0xE0, 0x30, 0xE0, 0x11, 0x90, 0x81, 0x1F, 0xE0, - 0x30, 0xE0, 0x07, 0x31, 0x73, 0xBF, 0x01, 0x05, - 0x41, 0x5B, 0x12, 0x4E, 0x3C, 0x22, 0xD3, 0x10, - 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81, 0x1E, - 0xE0, 0xB4, 0x01, 0x04, 0x7F, 0x04, 0x80, 0x0B, - 0x31, 0x73, 0xBF, 0x01, 0x04, 0x7F, 0x01, 0x80, - 0x02, 0x7F, 0x02, 0x71, 0x0E, 0xD0, 0xD0, 0x92, - 0xAF, 0x22, 0x90, 0x81, 0x4B, 0xE0, 0x60, 0x0F, - 0xE4, 0xF0, 0x90, 0x05, 0x53, 0xE0, 0x44, 0x02, - 0xF0, 0x90, 0x05, 0xFC, 0xE0, 0x04, 0xF0, 0x90, - 0x81, 0x1F, 0xE0, 0x30, 0xE0, 0x10, 0xA3, 0x74, - 0x01, 0xF0, 0x90, 0x81, 0x1F, 0xE0, 0xFF, 0xC3, - 0x13, 0x30, 0xE0, 0x02, 0x31, 0x9E, 0x11, 0xC4, - 0x90, 0x81, 0x3F, 0xE0, 0x30, 0xE0, 0x07, 0x91, - 0x65, 0x90, 0x05, 0x22, 0xE4, 0xF0, 0x22, 0x90, - 0x81, 0x1F, 0xE0, 0xFF, 0x30, 0xE0, 0x3D, 0x90, - 0x81, 0x23, 0xE0, 0x7E, 0x00, 0xB4, 0x02, 0x02, - 0x7E, 0x01, 0x90, 0x81, 0x22, 0xE0, 0x7D, 0x00, - 0xB4, 0x04, 0x02, 0x7D, 0x01, 0xED, 0x4E, 0x70, - 0x23, 0xEF, 0xC3, 0x13, 0x30, 0xE0, 0x02, 0x21, - 0x9E, 0x51, 0x45, 0x90, 0x81, 0x23, 0xE0, 0xB4, - 0x08, 0x06, 0xE4, 0xFD, 0x7F, 0x0C, 0x80, 0x09, - 0x90, 0x81, 0x23, 0xE0, 0x70, 0x06, 0xFD, 0x7F, - 0x04, 0x12, 0x47, 0x3D, 0x22, 0x90, 0x81, 0x1E, - 0xE0, 0xB4, 0x01, 0x0F, 0x90, 0x81, 0x23, 0xE0, - 0x64, 0x02, 0x60, 0x07, 0x7D, 0x01, 0x7F, 0x02, - 0x12, 0x47, 0x3D, 0x90, 0x81, 0x27, 0xE0, 0x64, - 0x02, 0x60, 0x14, 0x90, 0x81, 0x26, 0xE0, 0x54, - 0x0F, 0x60, 0x0C, 0x12, 0x4E, 0xAB, 0xEF, 0x70, - 0x06, 0xFD, 0x7F, 0x0C, 0x12, 0x47, 0x3D, 0x22, - 0x90, 0x81, 0x1F, 0xE0, 0xFF, 0x30, 0xE0, 0x3F, - 0x90, 0x81, 0x23, 0xE0, 0x7E, 0x00, 0xB4, 0x02, - 0x02, 0x7E, 0x01, 0x90, 0x81, 0x22, 0xE0, 0x7D, - 0x00, 0xB4, 0x04, 0x02, 0x7D, 0x01, 0xED, 0x4E, - 0x70, 0x25, 0xEF, 0xC3, 0x13, 0x30, 0xE0, 0x02, - 0x21, 0x9E, 0x12, 0x74, 0xAC, 0x90, 0x81, 0x23, - 0xE0, 0xB4, 0x0C, 0x06, 0xE4, 0xFD, 0x7F, 0x08, - 0x80, 0x0A, 0x90, 0x81, 0x23, 0xE0, 0xB4, 0x04, - 0x06, 0xE4, 0xFD, 0xFF, 0x12, 0x47, 0x3D, 0x22, - 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, - 0x81, 0xCB, 0x12, 0x45, 0x1F, 0x12, 0x1F, 0xA4, - 0xFF, 0x90, 0x81, 0x1E, 0xF0, 0xBF, 0x01, 0x12, - 0x90, 0x81, 0xCB, 0x12, 0x45, 0x16, 0x90, 0x00, - 0x01, 0x12, 0x1F, 0xBD, 0x64, 0x01, 0x60, 0x21, - 0x80, 0x1D, 0x90, 0x81, 0xCB, 0x12, 0x45, 0x16, - 0x90, 0x00, 0x01, 0x12, 0x1F, 0xBD, 0x64, 0x01, - 0x60, 0x0F, 0x90, 0x81, 0x1F, 0xE0, 0x20, 0xE0, - 0x06, 0xE4, 0xFF, 0x71, 0x0E, 0x80, 0x02, 0x31, - 0x9E, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, - 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81, 0x22, - 0xE0, 0x90, 0x82, 0x16, 0xF0, 0x6F, 0x70, 0x02, - 0x81, 0x04, 0xEF, 0x14, 0x60, 0x3E, 0x14, 0x60, - 0x62, 0x14, 0x70, 0x02, 0x61, 0xB8, 0x14, 0x70, - 0x02, 0x61, 0xDF, 0x24, 0x04, 0x60, 0x02, 0x81, - 0x04, 0x90, 0x82, 0x16, 0xE0, 0xFF, 0xB4, 0x04, - 0x04, 0x91, 0x41, 0x81, 0x04, 0xEF, 0xB4, 0x02, - 0x04, 0x91, 0x50, 0x81, 0x04, 0x90, 0x82, 0x16, - 0xE0, 0xFF, 0xB4, 0x03, 0x04, 0x91, 0x54, 0x81, - 0x04, 0xEF, 0x64, 0x01, 0x60, 0x02, 0x81, 0x04, - 0x91, 0x43, 0x81, 0x04, 0x90, 0x82, 0x16, 0xE0, - 0xFF, 0xB4, 0x04, 0x04, 0x91, 0xF3, 0x81, 0x04, - 0xEF, 0xB4, 0x02, 0x04, 0x91, 0x58, 0x81, 0x04, - 0x90, 0x82, 0x16, 0xE0, 0xFF, 0xB4, 0x03, 0x04, - 0x91, 0xE8, 0x81, 0x04, 0xEF, 0x70, 0x7D, 0x91, - 0x2B, 0x80, 0x79, 0x90, 0x82, 0x16, 0xE0, 0xB4, - 0x04, 0x05, 0x12, 0x74, 0x60, 0x80, 0x6D, 0x90, - 0x82, 0x16, 0xE0, 0xB4, 0x01, 0x04, 0x91, 0x21, - 0x80, 0x62, 0x90, 0x82, 0x16, 0xE0, 0xB4, 0x03, - 0x05, 0x12, 0x74, 0x71, 0x80, 0x56, 0x90, 0x82, - 0x16, 0xE0, 0x70, 0x50, 0x91, 0x1F, 0x80, 0x4C, - 0x90, 0x82, 0x16, 0xE0, 0xFF, 0xB4, 0x04, 0x05, - 0x12, 0x74, 0x4C, 0x80, 0x3F, 0xEF, 0xB4, 0x01, - 0x04, 0x91, 0x34, 0x80, 0x37, 0xEF, 0xB4, 0x02, - 0x04, 0x91, 0xDF, 0x80, 0x2F, 0x90, 0x82, 0x16, - 0xE0, 0x70, 0x29, 0x91, 0x32, 0x80, 0x25, 0x90, - 0x82, 0x16, 0xE0, 0xFF, 0xB4, 0x03, 0x05, 0x12, - 0x74, 0x7B, 0x80, 0x18, 0xEF, 0xB4, 0x01, 0x04, - 0x91, 0x0B, 0x80, 0x10, 0xEF, 0xB4, 0x02, 0x04, - 0xB1, 0x06, 0x80, 0x08, 0x90, 0x82, 0x16, 0xE0, - 0x70, 0x02, 0x91, 0x09, 0xD0, 0xD0, 0x92, 0xAF, - 0x22, 0x91, 0x2B, 0x90, 0x05, 0x22, 0x74, 0x6F, - 0xF0, 0x90, 0x05, 0x27, 0xE0, 0x54, 0xBF, 0xF0, - 0x90, 0x81, 0x22, 0x74, 0x04, 0xF0, 0x22, 0x91, - 0x2B, 0x12, 0x49, 0xDD, 0x90, 0x81, 0x22, 0x74, - 0x02, 0xF0, 0x22, 0x90, 0x81, 0x22, 0x74, 0x01, - 0xF0, 0x22, 0x91, 0x2B, 0x90, 0x05, 0x22, 0x74, - 0xFF, 0xF0, 0x90, 0x81, 0x22, 0x74, 0x03, 0xF0, - 0x22, 0x91, 0xF3, 0x90, 0x05, 0x27, 0xE0, 0x54, - 0xBF, 0xF0, 0xE4, 0x90, 0x81, 0x22, 0xF0, 0x22, - 0x91, 0x58, 0x80, 0xEF, 0x91, 0xE8, 0x80, 0xEB, - 0x91, 0x65, 0x90, 0x05, 0x22, 0xE4, 0xF0, 0x90, - 0x81, 0x22, 0x04, 0xF0, 0x22, 0xD3, 0x10, 0xAF, - 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x01, 0x01, 0xE0, - 0x44, 0x02, 0xF0, 0x90, 0x01, 0x00, 0x74, 0xFF, - 0xF0, 0x90, 0x06, 0xB7, 0x74, 0x09, 0xF0, 0x90, - 0x06, 0xB4, 0x74, 0x86, 0xF0, 0x7F, 0x7C, 0x7E, - 0x08, 0x12, 0x2D, 0x5C, 0xEC, 0x54, 0x7F, 0xFC, - 0x90, 0x82, 0x01, 0x12, 0x20, 0xCE, 0x90, 0x82, - 0x01, 0x12, 0x44, 0xD9, 0x90, 0x85, 0xBB, 0x12, - 0x20, 0xCE, 0x7F, 0x7C, 0x7E, 0x08, 0x12, 0x2E, - 0xA2, 0x90, 0x85, 0xBB, 0x12, 0x20, 0xDA, 0xCC, - 0xC0, 0x00, 0xC0, 0x7F, 0x8C, 0x7E, 0x08, 0x12, - 0x2E, 0xA2, 0x90, 0x85, 0xBB, 0x12, 0x20, 0xDA, - 0x00, 0xC0, 0x00, 0x14, 0x7F, 0x70, 0x7E, 0x0E, - 0x12, 0x2E, 0xA2, 0x90, 0x81, 0xF9, 0x12, 0x20, - 0xDA, 0x00, 0x03, 0x3E, 0x60, 0xE4, 0xFD, 0xFF, - 0xB1, 0x1C, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x91, - 0x65, 0x90, 0x81, 0x22, 0x74, 0x03, 0xF0, 0x22, - 0x90, 0x05, 0x22, 0xE4, 0xF0, 0x90, 0x81, 0x22, - 0x04, 0xF0, 0x22, 0x90, 0x05, 0x22, 0xE4, 0xF0, - 0x90, 0x05, 0x27, 0xE0, 0x44, 0x40, 0xF0, 0x90, - 0x81, 0x22, 0x74, 0x01, 0xF0, 0x22, 0x91, 0x65, - 0x90, 0x05, 0x22, 0x74, 0x6F, 0xF0, 0x90, 0x05, - 0x27, 0xE0, 0x54, 0xBF, 0xF0, 0x90, 0x81, 0x22, - 0x74, 0x04, 0xF0, 0x22, 0xD3, 0x10, 0xAF, 0x01, - 0xC3, 0xC0, 0xD0, 0xC0, 0x07, 0xC0, 0x05, 0x90, - 0x81, 0xF9, 0x12, 0x44, 0xD9, 0x90, 0x81, 0xE5, - 0x12, 0x20, 0xCE, 0xD0, 0x05, 0xD0, 0x07, 0x12, - 0x60, 0xF5, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, - 0x81, 0xC8, 0x12, 0x45, 0x1F, 0xEF, 0x12, 0x45, - 0x28, 0x55, 0x71, 0x00, 0x55, 0x7A, 0x01, 0x55, - 0x83, 0x02, 0x55, 0x8B, 0x03, 0x55, 0x94, 0x04, - 0x55, 0x9C, 0x20, 0x55, 0xA4, 0x21, 0x55, 0xAD, - 0x23, 0x55, 0xB5, 0x24, 0x55, 0xBE, 0x25, 0x55, - 0xC7, 0x26, 0x55, 0xCF, 0xC0, 0x00, 0x00, 0x55, - 0xD8, 0x90, 0x81, 0xC8, 0x12, 0x45, 0x16, 0x02, - 0x6A, 0xB0, 0x90, 0x81, 0xC8, 0x12, 0x45, 0x16, - 0x02, 0x65, 0x81, 0x90, 0x81, 0xC8, 0x12, 0x45, - 0x16, 0x41, 0xC0, 0x90, 0x81, 0xC8, 0x12, 0x45, - 0x16, 0x02, 0x75, 0xD8, 0x90, 0x81, 0xC8, 0x12, - 0x45, 0x16, 0x80, 0x44, 0x90, 0x81, 0xC8, 0x12, - 0x45, 0x16, 0xC1, 0x4B, 0x90, 0x81, 0xC8, 0x12, - 0x45, 0x16, 0x02, 0x6A, 0xF8, 0x90, 0x81, 0xC8, - 0x12, 0x45, 0x16, 0xE1, 0xE1, 0x90, 0x81, 0xC8, - 0x12, 0x45, 0x16, 0x02, 0x4A, 0x6C, 0x90, 0x81, - 0xC8, 0x12, 0x45, 0x16, 0x02, 0x6B, 0x3E, 0x90, - 0x81, 0xC8, 0x12, 0x45, 0x16, 0x80, 0x3E, 0x90, - 0x81, 0xC8, 0x12, 0x45, 0x16, 0x02, 0x6B, 0x4E, - 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x01, 0xF0, 0x22, - 0x12, 0x5A, 0x4B, 0x12, 0x1F, 0xA4, 0xFF, 0x54, - 0x01, 0xFE, 0x90, 0x81, 0x45, 0xE0, 0x54, 0xFE, - 0x4E, 0xF0, 0xEF, 0xC3, 0x13, 0x30, 0xE0, 0x14, - 0x90, 0x00, 0x01, 0x12, 0x1F, 0xBD, 0x90, 0x81, - 0x46, 0xF0, 0x90, 0x00, 0x02, 0x12, 0x1F, 0xBD, - 0x90, 0x81, 0x47, 0xF0, 0x22, 0x12, 0x1F, 0xA4, - 0xFF, 0x54, 0x01, 0xFE, 0x90, 0x81, 0x3F, 0xE0, - 0x54, 0xFE, 0x4E, 0xF0, 0x90, 0x00, 0x01, 0x12, - 0x1F, 0xBD, 0xFE, 0x90, 0x05, 0x54, 0xE0, 0xC3, - 0x9E, 0x90, 0x81, 0x40, 0xF0, 0xEF, 0x20, 0xE0, - 0x07, 0x91, 0x65, 0x90, 0x05, 0x22, 0xE4, 0xF0, - 0x90, 0x81, 0x3F, 0xE0, 0x54, 0x01, 0x90, 0x01, - 0xBC, 0xF0, 0x90, 0x81, 0x40, 0xE0, 0x90, 0x01, - 0xBD, 0xF0, 0x22, 0x12, 0x1F, 0xA4, 0xFF, 0x54, - 0x7F, 0x90, 0x81, 0x27, 0xF0, 0xEF, 0xC4, 0x13, - 0x13, 0x13, 0x54, 0x01, 0xA3, 0xF0, 0x90, 0x00, - 0x01, 0x12, 0x1F, 0xBD, 0xFF, 0x54, 0xF0, 0xC4, - 0x54, 0x0F, 0xFE, 0x90, 0x81, 0x26, 0xE0, 0x54, - 0xF0, 0x4E, 0xF0, 0x90, 0x00, 0x03, 0x12, 0x1F, - 0xBD, 0x54, 0x01, 0x25, 0xE0, 0xFE, 0x90, 0x81, - 0x24, 0xE0, 0x54, 0xFD, 0x4E, 0xF0, 0xEF, 0x54, - 0x0F, 0xC4, 0x54, 0xF0, 0xFF, 0x90, 0x81, 0x26, - 0xE0, 0x54, 0x0F, 0x4F, 0xF0, 0x90, 0x00, 0x04, - 0x12, 0x1F, 0xBD, 0x90, 0x81, 0x29, 0xF0, 0xD1, - 0xC6, 0x90, 0x01, 0xB9, 0x74, 0x01, 0xF0, 0x90, - 0x01, 0xB8, 0xF0, 0x90, 0x81, 0x27, 0xE0, 0x90, - 0x01, 0xBA, 0xF0, 0x90, 0x81, 0x29, 0xE0, 0x90, - 0x01, 0xBB, 0xF0, 0x90, 0x81, 0x26, 0xE0, 0x54, - 0x0F, 0x90, 0x01, 0xBE, 0xF0, 0x22, 0x90, 0x81, - 0xCB, 0x12, 0x45, 0x1F, 0x12, 0x72, 0xB3, 0x90, - 0x81, 0x27, 0xE0, 0xFF, 0x12, 0x4C, 0x3E, 0x90, - 0x81, 0x27, 0xE0, 0x60, 0x19, 0x90, 0x81, 0xCB, - 0x12, 0x45, 0x16, 0x90, 0x00, 0x01, 0x12, 0x1F, - 0xBD, 0x54, 0x0F, 0xFF, 0x90, 0x00, 0x02, 0x12, - 0x1F, 0xBD, 0xFD, 0x12, 0x72, 0xC4, 0x22, 0xC0, - 0xE0, 0xC0, 0xF0, 0xC0, 0x83, 0xC0, 0x82, 0xC0, - 0xD0, 0x75, 0xD0, 0x00, 0xC0, 0x00, 0xC0, 0x01, - 0xC0, 0x02, 0xC0, 0x03, 0xC0, 0x04, 0xC0, 0x05, - 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x01, 0xC4, 0x74, - 0xF7, 0xF0, 0x74, 0x56, 0xA3, 0xF0, 0x12, 0x6C, - 0xA5, 0xE5, 0x49, 0x30, 0xE1, 0x03, 0x12, 0x6F, - 0x79, 0xE5, 0x49, 0x30, 0xE2, 0x02, 0xF1, 0xA5, - 0xE5, 0x49, 0x30, 0xE3, 0x03, 0x12, 0x6F, 0x8D, - 0xE5, 0x4A, 0x30, 0xE0, 0x03, 0x12, 0x6F, 0xC9, - 0xE5, 0x4A, 0x30, 0xE4, 0x03, 0x12, 0x70, 0x22, - 0xE5, 0x4B, 0x30, 0xE1, 0x02, 0x51, 0x78, 0xE5, - 0x4B, 0x30, 0xE0, 0x02, 0x31, 0xFF, 0xE5, 0x4B, - 0x30, 0xE3, 0x02, 0xF1, 0xE0, 0xE5, 0x4C, 0x30, - 0xE1, 0x05, 0x7F, 0x03, 0x12, 0x44, 0x27, 0xE5, - 0x4C, 0x30, 0xE4, 0x03, 0x12, 0x4E, 0xC4, 0xE5, - 0x4C, 0x30, 0xE5, 0x03, 0x12, 0x70, 0x38, 0xE5, - 0x4C, 0x30, 0xE6, 0x03, 0x12, 0x70, 0xCE, 0x74, - 0xF7, 0x04, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x56, - 0xA3, 0xF0, 0xD0, 0x07, 0xD0, 0x06, 0xD0, 0x05, - 0xD0, 0x04, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, - 0xD0, 0x00, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83, - 0xD0, 0xF0, 0xD0, 0xE0, 0x32, 0x90, 0x81, 0x27, - 0xE0, 0x60, 0x34, 0x90, 0x06, 0x92, 0xE0, 0x30, - 0xE0, 0x23, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x3A, - 0xE0, 0xC3, 0x13, 0x54, 0x7F, 0xF5, 0x1E, 0xE4, - 0xFB, 0xFD, 0x7F, 0x58, 0x7E, 0x01, 0x11, 0x05, - 0x90, 0x01, 0x5B, 0x74, 0x05, 0xF0, 0x90, 0x06, - 0x92, 0x74, 0x01, 0xF0, 0x22, 0x90, 0x81, 0x24, - 0xE0, 0x54, 0xF7, 0xF0, 0x12, 0x47, 0x2A, 0x22, - 0x22, 0x12, 0x1F, 0xA4, 0x90, 0x81, 0x31, 0xF0, - 0x22, 0x90, 0x01, 0xC8, 0xE4, 0xF0, 0xA3, 0xF0, - 0xA3, 0xF0, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0x51, - 0x7F, 0xFF, 0xFE, 0x12, 0x2B, 0x27, 0xBF, 0x01, - 0x09, 0x90, 0x81, 0x51, 0xE0, 0x64, 0x03, 0x60, - 0x03, 0x22, 0x01, 0xAB, 0xE4, 0x90, 0x81, 0x56, - 0xF0, 0x90, 0x81, 0x56, 0xE0, 0xFF, 0xC3, 0x94, - 0x02, 0x40, 0x02, 0x01, 0xE6, 0xC3, 0x74, 0xFE, - 0x9F, 0xFF, 0xE4, 0x94, 0x00, 0xFE, 0x7B, 0x01, - 0x7A, 0x81, 0x79, 0x52, 0x12, 0x2B, 0x27, 0xEF, - 0x64, 0x01, 0x70, 0x77, 0x90, 0x81, 0x52, 0xE0, - 0xFF, 0x54, 0xC0, 0xFE, 0x60, 0x05, 0xEF, 0x54, - 0x0C, 0x70, 0x16, 0x90, 0x81, 0x52, 0xE0, 0xFF, - 0x54, 0x30, 0x60, 0x67, 0xEF, 0x54, 0x03, 0x60, - 0x62, 0x90, 0x81, 0x53, 0x74, 0x01, 0xF0, 0x80, - 0x05, 0xE4, 0x90, 0x81, 0x53, 0xF0, 0x90, 0x81, - 0x53, 0xE0, 0x90, 0x81, 0x52, 0x70, 0x16, 0xE0, - 0xFF, 0xEE, 0x13, 0x13, 0x54, 0x3F, 0x90, 0x81, - 0x54, 0xF0, 0xEF, 0x54, 0x0C, 0x13, 0x13, 0x54, - 0x3F, 0xA3, 0xF0, 0x80, 0x0D, 0xE0, 0xFE, 0x54, - 0x30, 0x90, 0x81, 0x54, 0xF0, 0xEE, 0x54, 0x03, - 0xA3, 0xF0, 0x90, 0x81, 0x54, 0xE0, 0x64, 0x30, - 0x70, 0x54, 0xA3, 0xE0, 0x64, 0x02, 0x70, 0x4E, - 0x90, 0x00, 0xF5, 0xE0, 0x54, 0x40, 0x90, 0x81, - 0x57, 0xF0, 0xE0, 0x70, 0x41, 0xA3, 0x74, 0x02, - 0xF0, 0x80, 0x10, 0x90, 0x81, 0x58, 0x74, 0x01, - 0xF0, 0x80, 0x08, 0x90, 0x81, 0x56, 0xE0, 0x04, - 0xF0, 0x01, 0x11, 0x90, 0x01, 0xC4, 0x74, 0xE9, - 0xF0, 0x74, 0x57, 0xA3, 0xF0, 0x90, 0x81, 0x58, - 0xE0, 0x90, 0x01, 0xC8, 0xF0, 0x90, 0x81, 0x52, - 0xE0, 0x90, 0x01, 0xC9, 0xF0, 0x90, 0x81, 0x53, - 0xE0, 0x90, 0x01, 0xCA, 0xF0, 0xE4, 0xFD, 0x7F, - 0x1F, 0x12, 0x32, 0x1E, 0x80, 0xD5, 0x22, 0x90, - 0x00, 0xF7, 0xE0, 0x20, 0xE7, 0x09, 0xE0, 0x7F, - 0x01, 0x20, 0xE6, 0x0C, 0x7F, 0x02, 0x22, 0x90, - 0x00, 0xF7, 0xE0, 0x30, 0xE6, 0x02, 0x7F, 0x03, - 0x22, 0x11, 0xE7, 0x90, 0x80, 0x3C, 0xEF, 0xF0, - 0x31, 0x13, 0x90, 0x01, 0x64, 0x74, 0x01, 0xF0, - 0x02, 0x2D, 0xA7, 0x31, 0x81, 0x31, 0xB1, 0x31, - 0x40, 0x31, 0x5F, 0xE4, 0xF5, 0x35, 0xF5, 0x36, - 0xF5, 0x37, 0xF5, 0x38, 0xAD, 0x35, 0x7F, 0x50, - 0x12, 0x32, 0x1E, 0xAD, 0x36, 0x7F, 0x51, 0x12, - 0x32, 0x1E, 0xAD, 0x37, 0x7F, 0x52, 0x12, 0x32, - 0x1E, 0xAD, 0x38, 0x7F, 0x53, 0x02, 0x32, 0x1E, - 0x75, 0x3D, 0x10, 0xE4, 0xF5, 0x3E, 0x75, 0x3F, - 0x07, 0x75, 0x40, 0x02, 0x90, 0x01, 0x30, 0xE5, - 0x3D, 0xF0, 0xA3, 0xE5, 0x3E, 0xF0, 0xA3, 0xE5, - 0x3F, 0xF0, 0xA3, 0xE5, 0x40, 0xF0, 0x22, 0x75, - 0x45, 0x0E, 0x75, 0x46, 0x01, 0x43, 0x46, 0x10, - 0x75, 0x47, 0x03, 0x75, 0x48, 0x62, 0x90, 0x01, - 0x38, 0xE5, 0x45, 0xF0, 0xA3, 0xE5, 0x46, 0xF0, - 0xA3, 0xE5, 0x47, 0xF0, 0xA3, 0xE5, 0x48, 0xF0, - 0x22, 0x90, 0x01, 0x30, 0xE4, 0xF0, 0xA3, 0xF0, - 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x01, 0x38, 0xF0, - 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xFD, 0x7F, - 0x50, 0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x51, - 0x12, 0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x52, 0x12, - 0x32, 0x1E, 0xE4, 0xFD, 0x7F, 0x53, 0x02, 0x32, - 0x1E, 0x90, 0x01, 0x34, 0x74, 0xFF, 0xF0, 0xA3, - 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x01, 0x3C, - 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xFD, - 0x7F, 0x54, 0x12, 0x32, 0x1E, 0x7D, 0xFF, 0x7F, - 0x55, 0x12, 0x32, 0x1E, 0x7D, 0xFF, 0x7F, 0x56, - 0x12, 0x32, 0x1E, 0x7D, 0xFF, 0x7F, 0x57, 0x02, - 0x32, 0x1E, 0x90, 0x00, 0x80, 0xE0, 0x44, 0x80, - 0xFD, 0x7F, 0x80, 0x12, 0x32, 0x1E, 0x90, 0xFD, - 0x00, 0xE0, 0x54, 0xBF, 0xF0, 0x12, 0x57, 0xE9, - 0x51, 0x77, 0x12, 0x32, 0x77, 0x51, 0xC9, 0x51, - 0x5E, 0x7F, 0x01, 0x12, 0x43, 0x15, 0x90, 0x81, - 0x41, 0x74, 0x02, 0xF0, 0xFF, 0x12, 0x43, 0x15, - 0x90, 0x81, 0x41, 0xE0, 0x04, 0xF0, 0x7F, 0x03, - 0x12, 0x43, 0x15, 0x90, 0x81, 0x41, 0xE0, 0x04, - 0xF0, 0x31, 0x01, 0x51, 0x3F, 0x90, 0x00, 0x80, - 0xE0, 0x44, 0x40, 0xFD, 0x7F, 0x80, 0x12, 0x32, - 0x1E, 0x75, 0x20, 0xFF, 0x51, 0x68, 0x51, 0xF9, - 0x51, 0x7F, 0xE4, 0xFF, 0x02, 0x43, 0x9E, 0x51, - 0x62, 0x51, 0x6F, 0x51, 0xA7, 0x71, 0x4F, 0x51, - 0x8A, 0x51, 0x95, 0x90, 0x81, 0x45, 0xE0, 0x54, - 0xFE, 0xF0, 0xA3, 0x74, 0x03, 0xF0, 0xA3, 0xF0, - 0xE4, 0xA3, 0xF0, 0xA3, 0xF0, 0x22, 0xE4, 0xF5, - 0x4D, 0x22, 0xE4, 0x90, 0x80, 0xDE, 0xF0, 0x22, - 0x75, 0xE8, 0x03, 0x75, 0xA8, 0x84, 0x22, 0xE4, - 0x90, 0x80, 0xD8, 0xF0, 0xA3, 0xF0, 0x22, 0x90, - 0x01, 0x94, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0x90, - 0x01, 0xE4, 0x74, 0x0B, 0xF0, 0xA3, 0x74, 0x01, - 0xF0, 0x22, 0x90, 0x81, 0x3F, 0xE0, 0x54, 0xFE, - 0xF0, 0xE4, 0xA3, 0xF0, 0x22, 0x90, 0x81, 0x42, - 0xE0, 0x54, 0xFE, 0xF0, 0x54, 0x7F, 0xF0, 0xA3, - 0x74, 0x0A, 0xF0, 0xE4, 0xA3, 0xF0, 0x22, 0x90, - 0x81, 0x1F, 0xE0, 0x54, 0xFE, 0xF0, 0x54, 0xFD, - 0xF0, 0x54, 0xFB, 0xF0, 0x54, 0xF7, 0xF0, 0x54, - 0xEF, 0xF0, 0x54, 0xDF, 0xF0, 0xE4, 0xA3, 0xF0, - 0xA3, 0xF0, 0xA3, 0xF0, 0xA3, 0x74, 0x0C, 0xF0, - 0x22, 0x90, 0x01, 0x01, 0xE0, 0x44, 0x04, 0xF0, - 0x90, 0x01, 0x9C, 0x74, 0x7E, 0xF0, 0xA3, 0x74, - 0x92, 0xF0, 0xA3, 0x74, 0xA0, 0xF0, 0xA3, 0x74, - 0x24, 0xF0, 0x90, 0x01, 0x9B, 0x74, 0x49, 0xF0, - 0x90, 0x01, 0x9A, 0x74, 0xE0, 0xF0, 0x90, 0x01, - 0x99, 0xE4, 0xF0, 0x90, 0x01, 0x98, 0x04, 0xF0, - 0x22, 0xE4, 0x90, 0x81, 0x51, 0xF0, 0xA3, 0xF0, - 0x90, 0x01, 0x98, 0xE0, 0x7F, 0x00, 0x30, 0xE4, - 0x02, 0x7F, 0x01, 0xEF, 0x64, 0x01, 0x60, 0x3E, - 0xC3, 0x90, 0x81, 0x52, 0xE0, 0x94, 0x88, 0x90, - 0x81, 0x51, 0xE0, 0x94, 0x13, 0x40, 0x08, 0x90, - 0x01, 0xC1, 0xE0, 0x44, 0x10, 0xF0, 0x22, 0x90, - 0x81, 0x51, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x44, - 0xA9, 0x7F, 0x14, 0x7E, 0x00, 0x12, 0x32, 0xAA, - 0xD3, 0x90, 0x81, 0x52, 0xE0, 0x94, 0x32, 0x90, - 0x81, 0x51, 0xE0, 0x94, 0x00, 0x40, 0xB9, 0x90, - 0x01, 0xC6, 0xE0, 0x30, 0xE3, 0xB2, 0x22, 0xE4, - 0x90, 0x81, 0x27, 0xF0, 0xA3, 0xF0, 0x90, 0x81, - 0x26, 0xE0, 0x54, 0x0F, 0xF0, 0x54, 0xF0, 0xF0, - 0x90, 0x81, 0x24, 0xE0, 0x54, 0xFD, 0xF0, 0x54, - 0xF7, 0xF0, 0x54, 0xEF, 0xF0, 0x90, 0x81, 0x2D, - 0x74, 0x01, 0xF0, 0xA3, 0xF0, 0x90, 0x81, 0x24, - 0xE0, 0x54, 0xFB, 0xF0, 0xA3, 0xE0, 0x54, 0xFB, - 0xF0, 0xE4, 0x90, 0x81, 0x30, 0xF0, 0x90, 0x81, - 0x2F, 0x74, 0x07, 0xF0, 0x90, 0x81, 0x32, 0xE4, - 0xF0, 0xA3, 0x74, 0x02, 0xF0, 0xE4, 0x90, 0x81, - 0x2B, 0xF0, 0x90, 0x81, 0x24, 0xE0, 0x54, 0xFE, - 0xF0, 0x90, 0x81, 0x29, 0x74, 0x0C, 0xF0, 0x90, - 0x81, 0x24, 0xE0, 0x54, 0xDF, 0xF0, 0x90, 0x81, - 0x2A, 0x74, 0x0C, 0xF0, 0x90, 0x81, 0x24, 0xE0, - 0x54, 0xBF, 0xF0, 0x54, 0x7F, 0xF0, 0xA3, 0xE0, - 0x54, 0xFE, 0xF0, 0x54, 0xFD, 0xF0, 0x54, 0xF7, - 0xF0, 0x90, 0x81, 0x34, 0x12, 0x20, 0xDA, 0x00, - 0x00, 0x00, 0x00, 0x90, 0x80, 0x3C, 0xE0, 0xB4, - 0x01, 0x08, 0x90, 0x81, 0x31, 0x74, 0x99, 0xF0, - 0x80, 0x12, 0x90, 0x80, 0x3C, 0xE0, 0x90, 0x81, - 0x31, 0xB4, 0x03, 0x05, 0x74, 0x90, 0xF0, 0x80, - 0x03, 0x74, 0x40, 0xF0, 0x90, 0x81, 0x38, 0x74, - 0x01, 0xF0, 0xA3, 0x74, 0x05, 0xF0, 0xA3, 0xE0, - 0x54, 0x01, 0x44, 0x28, 0xF0, 0xA3, 0x74, 0x05, - 0xF0, 0xE4, 0xA3, 0xF0, 0xA3, 0xE0, 0x54, 0xFD, - 0xF0, 0x54, 0xFB, 0xF0, 0x54, 0xF7, 0xF0, 0x54, - 0xEF, 0xF0, 0x54, 0xDF, 0xF0, 0x54, 0xBF, 0xF0, - 0xE4, 0xA3, 0xF0, 0x22, 0xE4, 0x90, 0x81, 0x59, - 0xF0, 0x90, 0x81, 0x59, 0xE0, 0x64, 0x01, 0xF0, - 0x24, 0x24, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x5C, - 0xA3, 0xF0, 0x90, 0x81, 0x2A, 0xE0, 0xFF, 0x90, - 0x81, 0x29, 0xE0, 0x6F, 0x60, 0x03, 0x12, 0x47, - 0x2A, 0xD1, 0x08, 0xBF, 0x01, 0x02, 0x91, 0x5F, - 0xB1, 0xF2, 0x12, 0x32, 0x9E, 0xBF, 0x01, 0x02, - 0xB1, 0x67, 0x12, 0x42, 0x4D, 0x80, 0xCA, 0xD3, - 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81, - 0x24, 0xE0, 0x30, 0xE0, 0x24, 0x90, 0x81, 0x1F, - 0xE0, 0xFF, 0x30, 0xE0, 0x1A, 0xC3, 0x13, 0x30, - 0xE0, 0x07, 0xB1, 0xFB, 0xBF, 0x01, 0x12, 0x80, - 0x0A, 0x90, 0x81, 0x23, 0xE0, 0xFF, 0x60, 0x03, - 0xB4, 0x08, 0x06, 0x91, 0x96, 0x80, 0x02, 0x91, - 0xA6, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, - 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0xB1, 0x22, 0x91, - 0xBA, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x90, 0x81, - 0x2A, 0xE0, 0x70, 0x0D, 0xD1, 0x2F, 0xBF, 0x01, - 0x08, 0x91, 0x96, 0x90, 0x01, 0xE5, 0xE0, 0x04, - 0xF0, 0x22, 0xB1, 0xF3, 0x90, 0x00, 0x08, 0xE0, - 0x54, 0xEF, 0xFD, 0x7F, 0x08, 0x12, 0x32, 0x1E, - 0xE4, 0xFF, 0x8F, 0x50, 0xE4, 0x90, 0x81, 0x5A, - 0xF0, 0xA3, 0xF0, 0x90, 0x01, 0x09, 0xE0, 0x7F, - 0x00, 0x30, 0xE7, 0x02, 0x7F, 0x01, 0xEF, 0x65, - 0x50, 0x60, 0x3E, 0xC3, 0x90, 0x81, 0x5B, 0xE0, - 0x94, 0x88, 0x90, 0x81, 0x5A, 0xE0, 0x94, 0x13, - 0x40, 0x08, 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x10, - 0xF0, 0x22, 0x90, 0x81, 0x5A, 0xE4, 0x75, 0xF0, - 0x01, 0x12, 0x44, 0xA9, 0x7F, 0x14, 0x7E, 0x00, - 0x12, 0x32, 0xAA, 0xD3, 0x90, 0x81, 0x5B, 0xE0, - 0x94, 0x32, 0x90, 0x81, 0x5A, 0xE0, 0x94, 0x00, - 0x40, 0xB9, 0x90, 0x01, 0xC6, 0xE0, 0x30, 0xE0, - 0xB2, 0x22, 0x90, 0x81, 0x31, 0xE0, 0xFD, 0x7F, - 0x93, 0x12, 0x32, 0x1E, 0x90, 0x81, 0x28, 0xE0, - 0x60, 0x12, 0x90, 0x01, 0x2F, 0xE0, 0x30, 0xE7, - 0x05, 0x74, 0x10, 0xF0, 0x80, 0x06, 0x90, 0x01, - 0x2F, 0x74, 0x90, 0xF0, 0x90, 0x00, 0x08, 0xE0, - 0x44, 0x10, 0xFD, 0x7F, 0x08, 0x12, 0x32, 0x1E, - 0x7F, 0x01, 0x91, 0xCA, 0x90, 0x00, 0x90, 0xE0, - 0x44, 0x01, 0xFD, 0x7F, 0x90, 0x12, 0x32, 0x1E, - 0x7F, 0x14, 0x7E, 0x00, 0x02, 0x32, 0xAA, 0xD3, - 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x2D, - 0xA7, 0xE4, 0xF5, 0x52, 0x12, 0x32, 0x9E, 0xEF, - 0x60, 0x73, 0x63, 0x52, 0x01, 0xE5, 0x52, 0x24, - 0x67, 0x90, 0x01, 0xC4, 0xF0, 0x74, 0x5D, 0xA3, - 0xF0, 0x90, 0x00, 0x88, 0xE0, 0xF5, 0x50, 0xF5, - 0x51, 0x54, 0x0F, 0x60, 0xDF, 0xE5, 0x50, 0x30, - 0xE0, 0x0B, 0x20, 0xE4, 0x03, 0x12, 0x29, 0xC5, - 0x53, 0x51, 0xEE, 0x80, 0x3F, 0xE5, 0x50, 0x30, - 0xE1, 0x16, 0x20, 0xE5, 0x0E, 0x12, 0x11, 0xBD, - 0xEF, 0x70, 0x03, 0x43, 0x51, 0x20, 0x90, 0x01, - 0x06, 0xE4, 0xF0, 0x53, 0x51, 0xFD, 0x80, 0x24, - 0xE5, 0x50, 0x30, 0xE2, 0x0B, 0x20, 0xE6, 0x03, - 0x12, 0x67, 0x06, 0x53, 0x51, 0xFB, 0x80, 0x14, - 0xE5, 0x50, 0x30, 0xE3, 0x0F, 0x20, 0xE7, 0x09, - 0x12, 0x61, 0x6E, 0xEF, 0x70, 0x03, 0x43, 0x51, - 0x80, 0x53, 0x51, 0xF7, 0xAD, 0x51, 0x7F, 0x88, - 0x12, 0x32, 0x1E, 0x80, 0x87, 0xD0, 0xD0, 0x92, - 0xAF, 0x22, 0x22, 0x90, 0x00, 0x90, 0xE0, 0x20, - 0xE0, 0xF9, 0x22, 0x90, 0x81, 0x22, 0xE0, 0x64, - 0x02, 0x7F, 0x01, 0x60, 0x02, 0x7F, 0x00, 0x22, - 0x7F, 0x02, 0x90, 0x81, 0x41, 0xE0, 0xFE, 0xEF, - 0xC3, 0x9E, 0x50, 0x18, 0xEF, 0x25, 0xE0, 0x24, - 0x81, 0xF8, 0xE6, 0x30, 0xE4, 0x0B, 0x90, 0x01, - 0xB8, 0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x7F, 0x00, - 0x22, 0x0F, 0x80, 0xDE, 0x7F, 0x01, 0x22, 0x90, - 0x02, 0x87, 0xE0, 0x60, 0x08, 0x90, 0x01, 0xB8, - 0x74, 0x01, 0xF0, 0x80, 0x17, 0x90, 0x02, 0x86, - 0xE0, 0x20, 0xE1, 0x08, 0x90, 0x01, 0xB8, 0x74, - 0x04, 0xF0, 0x80, 0x08, 0x90, 0x01, 0xB8, 0xE4, - 0xF0, 0x7F, 0x01, 0x22, 0x90, 0x01, 0xB9, 0x74, - 0x08, 0xF0, 0x7F, 0x00, 0x22, 0xE4, 0xFB, 0xFA, - 0xFD, 0x7F, 0x01, 0x12, 0x44, 0x4E, 0x90, 0x81, - 0xBD, 0xEF, 0xF0, 0x60, 0xF0, 0xD1, 0x71, 0x80, - 0xEC, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, - 0x90, 0x01, 0xCC, 0xE0, 0x54, 0x0F, 0x90, 0x81, - 0xBE, 0xF0, 0x90, 0x81, 0xBE, 0xE0, 0xFD, 0x70, - 0x02, 0xE1, 0x9C, 0x90, 0x82, 0x09, 0xE0, 0xFF, - 0x74, 0x01, 0x7E, 0x00, 0xA8, 0x07, 0x08, 0x80, - 0x05, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, - 0xFF, 0xEF, 0x5D, 0x70, 0x02, 0xE1, 0x95, 0x90, - 0x82, 0x09, 0xE0, 0x75, 0xF0, 0x04, 0x90, 0x01, - 0xD0, 0x12, 0x45, 0x0A, 0xE0, 0x90, 0x81, 0xBF, - 0xF0, 0x75, 0x13, 0x01, 0x75, 0x14, 0x81, 0x75, - 0x15, 0xBF, 0x75, 0x16, 0x01, 0x7B, 0x01, 0x7A, - 0x81, 0x79, 0xC0, 0x12, 0x2B, 0xED, 0x90, 0x82, - 0x09, 0xE0, 0x75, 0xF0, 0x04, 0x90, 0x01, 0xD1, - 0x12, 0x45, 0x0A, 0xE0, 0x90, 0x81, 0xC1, 0xF0, - 0x90, 0x82, 0x09, 0xE0, 0x75, 0xF0, 0x04, 0x90, - 0x01, 0xD2, 0x12, 0x45, 0x0A, 0xE0, 0x90, 0x81, - 0xC2, 0xF0, 0x90, 0x82, 0x09, 0xE0, 0x75, 0xF0, - 0x04, 0x90, 0x01, 0xD3, 0x12, 0x45, 0x0A, 0xE0, - 0x90, 0x81, 0xC3, 0xF0, 0x90, 0x82, 0x09, 0xE0, - 0x75, 0xF0, 0x04, 0x90, 0x01, 0xF0, 0x12, 0x45, - 0x0A, 0xE0, 0x90, 0x81, 0xC4, 0xF0, 0x90, 0x82, - 0x09, 0xE0, 0x75, 0xF0, 0x04, 0x90, 0x01, 0xF1, - 0x12, 0x45, 0x0A, 0xE0, 0x90, 0x81, 0xC5, 0xF0, - 0x90, 0x82, 0x09, 0xE0, 0x75, 0xF0, 0x04, 0x90, - 0x01, 0xF2, 0x12, 0x45, 0x0A, 0xE0, 0x90, 0x81, - 0xC6, 0xF0, 0x90, 0x82, 0x09, 0xE0, 0x75, 0xF0, - 0x04, 0x90, 0x01, 0xF3, 0x12, 0x45, 0x0A, 0xE0, - 0x90, 0x81, 0xC7, 0xF0, 0x90, 0x81, 0xBE, 0xE0, - 0xFF, 0x90, 0x82, 0x09, 0xE0, 0xFE, 0x74, 0x01, - 0xA8, 0x06, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, - 0xFC, 0xF4, 0x5F, 0x90, 0x81, 0xBE, 0xF0, 0x90, - 0x82, 0x09, 0xE0, 0xFF, 0x74, 0x01, 0xA8, 0x07, - 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0x90, - 0x01, 0xCC, 0xF0, 0x90, 0x81, 0xC0, 0xE0, 0xFF, - 0x7B, 0x01, 0x7A, 0x81, 0x79, 0xC1, 0x12, 0x55, - 0x3F, 0x90, 0x82, 0x09, 0xE0, 0x04, 0xF0, 0xE0, - 0x54, 0x03, 0xF0, 0xC1, 0x82, 0x90, 0x01, 0xC0, - 0xE0, 0x44, 0x02, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, - 0x22, 0xE4, 0xFB, 0xFA, 0xFD, 0x7F, 0x01, 0x12, - 0x44, 0x4E, 0x90, 0x81, 0xD0, 0xEF, 0xF0, 0x60, - 0xF0, 0x12, 0x6C, 0x19, 0x80, 0xEB, 0x90, 0x81, - 0xD4, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, 0xA3, 0x12, - 0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x90, - 0x81, 0xE2, 0xF0, 0x7F, 0x24, 0x7E, 0x08, 0x12, - 0x2D, 0x5C, 0x90, 0x81, 0xDA, 0x12, 0x20, 0xCE, - 0x90, 0x81, 0xD4, 0xE0, 0xFB, 0x70, 0x08, 0x90, - 0x81, 0xDA, 0x12, 0x44, 0xD9, 0x80, 0x16, 0xEB, - 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x62, 0xF5, 0x82, - 0xE4, 0x34, 0x87, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, - 0xE0, 0xFF, 0x12, 0x2D, 0x5C, 0x90, 0x81, 0xDE, - 0x12, 0x20, 0xCE, 0x90, 0x81, 0xD5, 0xE0, 0xFF, - 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x17, 0x12, 0x20, - 0xBB, 0xA8, 0x04, 0xA9, 0x05, 0xAA, 0x06, 0xAB, - 0x07, 0x90, 0x81, 0xDE, 0x12, 0x44, 0xD9, 0xED, - 0x54, 0x7F, 0xFD, 0xEC, 0x54, 0x80, 0xFC, 0x12, - 0x44, 0xCC, 0xEC, 0x44, 0x80, 0xFC, 0x90, 0x81, - 0xDE, 0x12, 0x20, 0xCE, 0x90, 0x81, 0xDA, 0x12, - 0x44, 0xD9, 0xEC, 0x54, 0x7F, 0xFC, 0x90, 0x85, - 0xBB, 0x12, 0x20, 0xCE, 0x7F, 0x24, 0x7E, 0x08, - 0x12, 0x2E, 0xA2, 0x90, 0x81, 0xD4, 0xE0, 0x75, - 0xF0, 0x08, 0xA4, 0x24, 0x62, 0xF5, 0x82, 0xE4, - 0x34, 0x87, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, - 0xFF, 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x81, 0xDE, - 0x12, 0x44, 0xD9, 0x90, 0x85, 0xBB, 0x12, 0x20, - 0xCE, 0xD0, 0x07, 0xD0, 0x06, 0x12, 0x2E, 0xA2, - 0x90, 0x81, 0xDA, 0x12, 0x44, 0xD9, 0xEC, 0x44, - 0x80, 0xFC, 0x90, 0x85, 0xBB, 0x12, 0x20, 0xCE, - 0x7F, 0x24, 0x7E, 0x08, 0x12, 0x2E, 0xA2, 0x90, - 0x81, 0xD4, 0xE0, 0x70, 0x04, 0x7F, 0x20, 0x80, - 0x09, 0x90, 0x81, 0xD4, 0xE0, 0xB4, 0x01, 0x16, - 0x7F, 0x28, 0x7E, 0x08, 0x12, 0x2D, 0x5C, 0x78, - 0x08, 0x12, 0x20, 0xA8, 0xEF, 0x54, 0x01, 0xFF, - 0xE4, 0x90, 0x81, 0xE2, 0xEF, 0xF0, 0x90, 0x81, - 0xE2, 0xE0, 0x90, 0x81, 0xD4, 0x60, 0x0E, 0xE0, - 0x75, 0xF0, 0x08, 0xA4, 0x24, 0x66, 0xF5, 0x82, - 0xE4, 0x34, 0x87, 0x80, 0x0C, 0xE0, 0x75, 0xF0, - 0x08, 0xA4, 0x24, 0x64, 0xF5, 0x82, 0xE4, 0x34, - 0x87, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, - 0x12, 0x2D, 0x5C, 0xED, 0x54, 0x0F, 0xFD, 0xE4, - 0xFC, 0x90, 0x81, 0xD6, 0x12, 0x20, 0xCE, 0x90, - 0x81, 0xD6, 0x02, 0x44, 0xD9, 0x90, 0x81, 0xE3, - 0xEF, 0xF0, 0xAB, 0x05, 0x90, 0x81, 0xE9, 0x12, - 0x20, 0xDA, 0x00, 0x00, 0x00, 0x00, 0xAF, 0x03, - 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x14, 0x12, 0x20, - 0xBB, 0xA8, 0x04, 0xA9, 0x05, 0xAA, 0x06, 0xAB, - 0x07, 0x90, 0x81, 0xE5, 0x12, 0x44, 0xD9, 0xED, - 0x54, 0x0F, 0xFD, 0xE4, 0xFC, 0x12, 0x44, 0xCC, - 0xEC, 0x54, 0x0F, 0xFC, 0x90, 0x81, 0xE9, 0x12, - 0x20, 0xCE, 0x90, 0x81, 0xE3, 0xE0, 0x75, 0xF0, - 0x08, 0xA4, 0x24, 0x60, 0xF5, 0x82, 0xE4, 0x34, - 0x87, 0xF5, 0x83, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, - 0xC0, 0x06, 0xC0, 0x07, 0x90, 0x81, 0xE9, 0x12, - 0x44, 0xD9, 0x90, 0x85, 0xBB, 0x12, 0x20, 0xCE, - 0xD0, 0x07, 0xD0, 0x06, 0x02, 0x2E, 0xA2, 0xD3, - 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x12, 0x5F, - 0xB6, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0x78, 0x10, - 0x74, 0x01, 0xF2, 0x90, 0x02, 0x09, 0xE0, 0x78, - 0x00, 0xF2, 0x08, 0x74, 0x20, 0xF2, 0x18, 0xE2, - 0xFF, 0x30, 0xE0, 0x05, 0x08, 0xE2, 0x24, 0x80, - 0xF2, 0xEF, 0xC3, 0x13, 0x90, 0xFD, 0x10, 0xF0, - 0x78, 0x01, 0xE2, 0x24, 0x00, 0xF5, 0x82, 0xE4, - 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x78, 0x03, 0xF2, - 0x64, 0x04, 0x60, 0x0D, 0xE2, 0xFF, 0x64, 0x08, - 0x60, 0x07, 0xEF, 0x64, 0x0C, 0x60, 0x02, 0x61, - 0xDE, 0xE4, 0x78, 0x02, 0xF2, 0x78, 0x03, 0xE2, - 0xFF, 0x18, 0xE2, 0xC3, 0x9F, 0x50, 0x2D, 0xE2, - 0xFD, 0x18, 0xE2, 0x2D, 0x90, 0x81, 0x5A, 0xF0, - 0xE0, 0xFF, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, - 0xFC, 0xF5, 0x83, 0xE0, 0xFE, 0x74, 0x04, 0x2D, - 0xF8, 0xEE, 0xF2, 0xEF, 0xB4, 0xFF, 0x06, 0x90, - 0xFD, 0x10, 0xE0, 0x04, 0xF0, 0x78, 0x02, 0xE2, - 0x04, 0xF2, 0x80, 0xC9, 0x78, 0x04, 0xE2, 0x78, - 0x12, 0xF2, 0xFF, 0x78, 0x05, 0xE2, 0x78, 0x11, - 0xF2, 0x78, 0x06, 0xE2, 0x78, 0x13, 0xF2, 0x78, - 0x07, 0xE2, 0x78, 0x14, 0xF2, 0x78, 0x08, 0xE2, - 0x78, 0x33, 0xF2, 0x78, 0x09, 0xE2, 0x78, 0x34, - 0xF2, 0x78, 0x0A, 0xE2, 0x78, 0x35, 0xF2, 0x78, - 0x0B, 0xE2, 0x78, 0x36, 0xF2, 0x78, 0x0C, 0xE2, - 0x78, 0x37, 0xF2, 0x78, 0x0D, 0xE2, 0x78, 0x38, - 0xF2, 0x78, 0x0E, 0xE2, 0x78, 0x39, 0xF2, 0x78, - 0x0F, 0xE2, 0x78, 0x3A, 0xF2, 0xE4, 0x78, 0x15, - 0xF2, 0xEF, 0x24, 0xF8, 0x60, 0x75, 0x24, 0xFC, - 0x60, 0x6C, 0x24, 0x08, 0x60, 0x02, 0x61, 0xC0, - 0x78, 0x11, 0xE2, 0xB4, 0x01, 0x05, 0x12, 0x29, - 0xC5, 0x61, 0xC5, 0x78, 0x11, 0xE2, 0xB4, 0x02, - 0x05, 0x12, 0x11, 0xBD, 0x61, 0xC5, 0x78, 0x11, - 0xE2, 0xB4, 0x03, 0x04, 0xF1, 0x06, 0x61, 0xC5, - 0x78, 0x11, 0xE2, 0xB4, 0x10, 0x17, 0x78, 0x14, - 0xE2, 0xFE, 0x18, 0xE2, 0xFD, 0xED, 0xFF, 0x78, - 0x16, 0xEE, 0xF2, 0xFE, 0x08, 0xEF, 0xF2, 0xFF, - 0x12, 0x32, 0xAA, 0x61, 0xC5, 0x78, 0x11, 0xE2, - 0xB4, 0x11, 0x17, 0x78, 0x14, 0xE2, 0xFE, 0x18, - 0xE2, 0xFD, 0xED, 0xFF, 0x78, 0x16, 0xEE, 0xF2, - 0xFE, 0x08, 0xEF, 0xF2, 0xFF, 0x12, 0x32, 0x06, - 0x61, 0xC5, 0x78, 0x11, 0xE2, 0xF4, 0x60, 0x02, - 0x61, 0xC5, 0x18, 0xF2, 0x61, 0xC5, 0x78, 0x15, - 0x74, 0x01, 0xF2, 0x78, 0x11, 0xE2, 0x64, 0x07, - 0x60, 0x02, 0x61, 0xAA, 0x78, 0x34, 0xE2, 0xFF, - 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x08, 0x12, 0x20, - 0xBB, 0xC0, 0x04, 0xA9, 0x05, 0xAA, 0x06, 0xAB, - 0x07, 0x78, 0x33, 0xE2, 0xFF, 0xE4, 0xFC, 0xFD, - 0xFE, 0xD0, 0x00, 0x12, 0x44, 0xCC, 0xC0, 0x04, - 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x78, 0x35, - 0xE2, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x10, - 0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, - 0x01, 0xD0, 0x00, 0x12, 0x44, 0xCC, 0x78, 0x18, - 0x12, 0x44, 0xFE, 0x78, 0x15, 0xE2, 0x70, 0x02, - 0x61, 0x93, 0x18, 0xE2, 0xFF, 0x18, 0xE2, 0xFD, - 0x31, 0x5F, 0x78, 0x1C, 0x12, 0x44, 0xFE, 0x78, - 0x38, 0xE2, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, - 0x08, 0x12, 0x20, 0xBB, 0xC0, 0x04, 0xA9, 0x05, - 0xAA, 0x06, 0xAB, 0x07, 0x78, 0x37, 0xE2, 0xFF, - 0xE4, 0xFC, 0xFD, 0xFE, 0xD0, 0x00, 0x12, 0x44, - 0xCC, 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, - 0x07, 0x78, 0x39, 0xE2, 0xFF, 0xE4, 0xFC, 0xFD, - 0xFE, 0x78, 0x10, 0x12, 0x20, 0xBB, 0xD0, 0x03, - 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, 0x12, 0x44, - 0xCC, 0x78, 0x20, 0x12, 0x44, 0xFE, 0x78, 0x20, - 0x12, 0x44, 0xE5, 0x12, 0x20, 0x9B, 0x78, 0x1C, - 0x12, 0x44, 0xF1, 0x12, 0x44, 0xBF, 0xC0, 0x04, - 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, 0x78, 0x18, - 0x12, 0x44, 0xE5, 0x78, 0x20, 0x12, 0x44, 0xF1, - 0x12, 0x44, 0xBF, 0xD0, 0x03, 0xD0, 0x02, 0xD0, - 0x01, 0xD0, 0x00, 0x12, 0x44, 0xCC, 0x78, 0x18, - 0x12, 0x44, 0xFE, 0x78, 0x18, 0x12, 0x44, 0xE5, - 0x90, 0x81, 0xF9, 0x12, 0x20, 0xCE, 0x78, 0x13, - 0xE2, 0xFD, 0x08, 0xE2, 0xFF, 0x12, 0x55, 0x1C, - 0x80, 0x1B, 0x78, 0x13, 0xE2, 0xFF, 0x08, 0xE2, - 0xFD, 0x78, 0x11, 0xE2, 0xFB, 0x78, 0x15, 0xE2, - 0x90, 0x81, 0xBC, 0xF0, 0x71, 0xE1, 0x80, 0x05, - 0x78, 0x10, 0x74, 0x02, 0xF2, 0x78, 0x10, 0xE2, - 0xFF, 0xC3, 0x94, 0x02, 0x50, 0x10, 0xEF, 0x60, - 0x0A, 0x78, 0x02, 0xE2, 0xFF, 0x18, 0xE2, 0x2F, - 0xF2, 0x21, 0x90, 0x7F, 0x01, 0x22, 0x7F, 0x00, - 0x22, 0xAC, 0x07, 0xED, 0xAD, 0x04, 0x78, 0x24, - 0xF2, 0xED, 0x08, 0xF2, 0xEB, 0xB4, 0x04, 0x07, - 0x78, 0x27, 0x74, 0x01, 0xF2, 0x80, 0x0E, 0xEB, - 0x78, 0x27, 0xB4, 0x05, 0x05, 0x74, 0x02, 0xF2, - 0x80, 0x03, 0x74, 0x04, 0xF2, 0xD3, 0x78, 0x25, - 0xE2, 0x94, 0xFF, 0x18, 0xE2, 0x94, 0x00, 0x50, - 0x63, 0xE4, 0x78, 0x26, 0xF2, 0x78, 0x27, 0xE2, - 0xFF, 0x18, 0xE2, 0xFE, 0xC3, 0x9F, 0x40, 0x02, - 0xA1, 0x7F, 0x74, 0x33, 0x2E, 0xF8, 0xE2, 0x78, - 0x28, 0xF2, 0x90, 0x81, 0xBC, 0xE0, 0x60, 0x2D, - 0x74, 0x37, 0x2E, 0xF8, 0xE2, 0x78, 0x32, 0xF2, - 0xEE, 0xFF, 0x78, 0x25, 0xE2, 0x2F, 0xFF, 0x18, - 0xE2, 0x34, 0x00, 0x8F, 0x82, 0xF5, 0x83, 0xE0, - 0x78, 0x29, 0xF2, 0x78, 0x32, 0xE2, 0xFF, 0xF4, - 0xFE, 0x78, 0x29, 0xE2, 0x5E, 0xFE, 0x18, 0xE2, - 0xFD, 0xEF, 0x5D, 0x4E, 0xF2, 0x78, 0x24, 0x08, - 0xE2, 0xFF, 0x08, 0xE2, 0x2F, 0xFF, 0x78, 0x28, - 0xE2, 0xFD, 0x12, 0x32, 0x1E, 0x78, 0x26, 0xE2, - 0x04, 0xF2, 0x80, 0xA1, 0xD3, 0x78, 0x25, 0xE2, - 0x94, 0xFF, 0x18, 0xE2, 0x94, 0x07, 0x50, 0x69, - 0xE4, 0x78, 0x26, 0xF2, 0x78, 0x27, 0xE2, 0xFF, - 0x18, 0xE2, 0xFE, 0xC3, 0x9F, 0x40, 0x02, 0xA1, - 0x7F, 0x74, 0x33, 0x2E, 0xF8, 0xE2, 0x78, 0x28, - 0xF2, 0x90, 0x81, 0xBC, 0xE0, 0x60, 0x2D, 0x78, - 0x26, 0xE2, 0xFF, 0xFD, 0x18, 0xE2, 0x2D, 0xFD, - 0x18, 0xE2, 0x34, 0x00, 0x8D, 0x82, 0xF5, 0x83, - 0xE0, 0x78, 0x29, 0xF2, 0x74, 0x37, 0x2F, 0xF8, - 0xE2, 0x78, 0x32, 0xF2, 0xE2, 0xFF, 0xF4, 0xFE, - 0x78, 0x29, 0xE2, 0x5E, 0xFE, 0x18, 0xE2, 0xFD, - 0xEF, 0x5D, 0x4E, 0xF2, 0x78, 0x28, 0xE2, 0xFF, - 0x78, 0x26, 0xE2, 0xFD, 0x18, 0xE2, 0x2D, 0xFD, - 0x18, 0xE2, 0x34, 0x00, 0x8D, 0x82, 0xF5, 0x83, - 0xEF, 0xF0, 0x78, 0x26, 0xE2, 0x04, 0xF2, 0x80, - 0x9B, 0x90, 0x81, 0xBC, 0xE0, 0x60, 0x0F, 0x78, - 0x24, 0xE2, 0xFE, 0x08, 0xE2, 0xFF, 0x12, 0x2D, - 0x5C, 0x78, 0x2E, 0x12, 0x44, 0xFE, 0xE4, 0x78, - 0x26, 0xF2, 0x78, 0x27, 0xE2, 0xFF, 0x18, 0xE2, - 0xFE, 0xC3, 0x9F, 0x50, 0x5D, 0x74, 0x33, 0x2E, - 0xF8, 0xE2, 0x78, 0x28, 0xF2, 0x90, 0x81, 0xBC, - 0xE0, 0x60, 0x2B, 0x78, 0x2E, 0x12, 0x44, 0xE5, - 0x78, 0x26, 0xE2, 0xFB, 0x75, 0xF0, 0x08, 0xA4, - 0xF9, 0xF8, 0x12, 0x20, 0xA8, 0x78, 0x29, 0xEF, - 0xF2, 0x74, 0x37, 0x2B, 0xF8, 0xE2, 0x78, 0x32, - 0xF2, 0xE2, 0xFE, 0xF4, 0x5F, 0xFF, 0x78, 0x28, - 0xE2, 0xFD, 0xEE, 0x5D, 0x4F, 0xF2, 0x78, 0x28, - 0xE2, 0xFF, 0x78, 0x26, 0xE2, 0xFD, 0xC3, 0x74, - 0x03, 0x9D, 0xFD, 0xE4, 0x94, 0x00, 0xFC, 0x7B, - 0xFE, 0x74, 0x2A, 0x2D, 0xF9, 0x74, 0x80, 0x3C, - 0xFA, 0xEF, 0x12, 0x1F, 0xEA, 0xE2, 0x04, 0xF2, - 0x80, 0x98, 0x78, 0x2A, 0x12, 0x44, 0xE5, 0x90, - 0x85, 0xBB, 0x12, 0x20, 0xCE, 0x78, 0x24, 0xE2, - 0xFE, 0x08, 0xE2, 0xFF, 0x12, 0x2E, 0xA2, 0x22, - 0x22, 0x90, 0x81, 0xCB, 0x12, 0x45, 0x1F, 0x90, - 0x00, 0x01, 0x12, 0x1F, 0xBD, 0xFF, 0xFE, 0x12, - 0x1F, 0xA4, 0xFD, 0xC3, 0x13, 0x30, 0xE0, 0x12, - 0x90, 0x81, 0xCB, 0x12, 0x45, 0x16, 0x90, 0x00, - 0x02, 0x12, 0x1F, 0xBD, 0x90, 0x81, 0xCF, 0xF0, - 0x80, 0x05, 0x90, 0x81, 0xCF, 0xEF, 0xF0, 0x90, - 0x81, 0xCE, 0xEE, 0xF0, 0x90, 0x81, 0xCF, 0xE0, - 0xFE, 0x90, 0x81, 0xCE, 0xE0, 0xFF, 0xD3, 0x9E, - 0x50, 0x38, 0x90, 0x81, 0xCB, 0x12, 0x45, 0x16, - 0x12, 0x1F, 0xA4, 0x54, 0x01, 0xFE, 0x74, 0xDE, - 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x80, 0xF5, 0x83, - 0xEE, 0xF0, 0x74, 0xDE, 0x2F, 0xF5, 0x82, 0xE4, - 0x34, 0x80, 0xF5, 0x83, 0xE0, 0x70, 0x04, 0xD1, - 0x25, 0x80, 0x07, 0x90, 0x81, 0xCE, 0xE0, 0xFF, - 0xB1, 0x80, 0x90, 0x81, 0xCE, 0xE0, 0x04, 0xF0, - 0x80, 0xBA, 0x90, 0x80, 0xDE, 0xE0, 0x70, 0x24, - 0x90, 0x81, 0x2A, 0xE0, 0x70, 0x04, 0xFF, 0x12, - 0x49, 0x93, 0x90, 0x81, 0x2A, 0xE0, 0x64, 0x0C, - 0x60, 0x02, 0xD1, 0x26, 0x90, 0x81, 0x24, 0xE0, - 0x54, 0xF7, 0xF0, 0x54, 0xEF, 0xF0, 0x54, 0xBF, - 0xF0, 0x54, 0x7F, 0xF0, 0x22, 0x22, 0x90, 0x06, - 0x04, 0xE0, 0x54, 0x7F, 0xF0, 0x90, 0x05, 0x22, - 0xE4, 0xF0, 0x90, 0x81, 0x2A, 0x74, 0x0C, 0xF0, - 0x22, 0x90, 0x81, 0xED, 0xEF, 0xF0, 0xA3, 0xED, - 0xF0, 0xAD, 0x03, 0xAC, 0x02, 0xE4, 0x90, 0x81, - 0xF5, 0xF0, 0xA3, 0xF0, 0x90, 0x01, 0xC4, 0x74, - 0x39, 0xF0, 0x74, 0x66, 0xA3, 0xF0, 0xEC, 0x54, - 0x3F, 0xFC, 0x90, 0x01, 0x40, 0xED, 0xF0, 0xAE, - 0x04, 0xEE, 0xA3, 0xF0, 0x90, 0x81, 0xED, 0xE0, - 0x24, 0x81, 0x60, 0x34, 0x24, 0xDA, 0x60, 0x1C, - 0x24, 0x3C, 0x70, 0x41, 0x90, 0x81, 0xEE, 0xE0, - 0xC4, 0x33, 0x33, 0x33, 0x54, 0x80, 0x90, 0x81, - 0xF2, 0xF0, 0xA3, 0x74, 0x69, 0xF0, 0xA3, 0x74, - 0x80, 0xF0, 0x80, 0x2C, 0x90, 0x81, 0xEE, 0xE0, - 0x54, 0x01, 0x90, 0x81, 0xF2, 0xF0, 0xA3, 0x74, - 0xA5, 0xF0, 0xA3, 0x74, 0x01, 0xF0, 0x80, 0x18, - 0x90, 0x81, 0xEE, 0xE0, 0xC4, 0x54, 0x10, 0x90, - 0x81, 0xF2, 0xF0, 0xA3, 0x74, 0x7F, 0xF0, 0xA3, - 0x74, 0x10, 0xF0, 0x80, 0x03, 0x7F, 0x00, 0x22, - 0x90, 0x81, 0xF3, 0xE0, 0x90, 0x01, 0x06, 0xF0, - 0x90, 0x81, 0xF2, 0xE0, 0x60, 0x0E, 0x90, 0x01, - 0x42, 0xF0, 0x90, 0x81, 0xF1, 0xE0, 0x90, 0x01, - 0x43, 0xF0, 0x80, 0x0D, 0x90, 0x01, 0x43, 0xE4, - 0xF0, 0x90, 0x81, 0xF2, 0xE0, 0x90, 0x01, 0x42, - 0xF0, 0x90, 0x81, 0xF4, 0xE0, 0xFF, 0x90, 0x01, - 0x42, 0xE0, 0x5F, 0xFF, 0x90, 0x81, 0xF2, 0xE0, - 0x6F, 0x60, 0xEE, 0x74, 0x39, 0x04, 0x90, 0x01, - 0xC4, 0xF0, 0x74, 0x66, 0xA3, 0xF0, 0x90, 0x01, - 0x43, 0xE4, 0xF0, 0x7F, 0x01, 0x22, 0xE4, 0x90, - 0x81, 0x6A, 0xF0, 0x90, 0x87, 0x5F, 0xE0, 0x90, - 0x81, 0x69, 0xF0, 0xE4, 0x90, 0x81, 0x76, 0xF0, - 0x90, 0x81, 0x66, 0xF0, 0x90, 0x81, 0x66, 0xE0, - 0xFF, 0xC3, 0x94, 0x40, 0x50, 0x15, 0x74, 0x79, - 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, - 0x74, 0xFF, 0xF0, 0x90, 0x81, 0x66, 0xE0, 0x04, - 0xF0, 0x80, 0xE1, 0xE4, 0x90, 0x81, 0x66, 0xF0, - 0x90, 0x81, 0x69, 0xE0, 0xFF, 0x90, 0x81, 0x66, - 0xE0, 0xFE, 0xC3, 0x9F, 0x40, 0x03, 0x02, 0x68, - 0x12, 0x74, 0xDF, 0x2E, 0xF9, 0xE4, 0x34, 0x86, - 0x75, 0x13, 0x01, 0xF5, 0x14, 0x89, 0x15, 0x75, - 0x16, 0x0A, 0x7B, 0x01, 0x7A, 0x81, 0x79, 0x5B, - 0x12, 0x2B, 0xED, 0x90, 0x81, 0x5C, 0xE0, 0xFF, - 0x12, 0x2F, 0x27, 0xEF, 0x04, 0x90, 0x81, 0x76, - 0xF0, 0x90, 0x81, 0x5B, 0xE0, 0xFF, 0xA3, 0xE0, - 0xFD, 0x12, 0x31, 0xEA, 0xEF, 0x24, 0xC8, 0x90, - 0x81, 0x78, 0xF0, 0x75, 0xF0, 0x08, 0xA4, 0xF0, - 0x90, 0x81, 0x5C, 0xE0, 0x54, 0x0F, 0x90, 0x81, - 0x77, 0xF0, 0xE4, 0x90, 0x81, 0x65, 0xF0, 0x90, - 0x81, 0x67, 0xF0, 0x90, 0x81, 0x67, 0xE0, 0xFF, - 0xC3, 0x94, 0x04, 0x50, 0x57, 0x90, 0x81, 0x77, - 0xE0, 0xFE, 0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, - 0x13, 0xD8, 0xFC, 0x20, 0xE0, 0x3E, 0x90, 0x81, - 0x67, 0xE0, 0x25, 0xE0, 0xFF, 0x90, 0x81, 0x78, - 0xE0, 0x2F, 0x24, 0x79, 0xF9, 0xE4, 0x34, 0x81, - 0xFA, 0x7B, 0x01, 0xC0, 0x03, 0xC0, 0x01, 0x90, - 0x81, 0x65, 0xE0, 0x75, 0xF0, 0x02, 0xA4, 0x24, - 0x5D, 0xF9, 0x74, 0x81, 0x35, 0xF0, 0x8B, 0x13, - 0xF5, 0x14, 0x89, 0x15, 0x75, 0x16, 0x02, 0xD0, - 0x01, 0xD0, 0x03, 0x12, 0x2B, 0xED, 0x90, 0x81, - 0x65, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0x67, 0xE0, - 0x04, 0xF0, 0x80, 0x9F, 0x90, 0x81, 0x76, 0xE0, - 0xFF, 0x90, 0x81, 0x66, 0xE0, 0x2F, 0xF0, 0x02, - 0x67, 0x40, 0xE4, 0x90, 0x81, 0x6A, 0xF0, 0x90, - 0x81, 0x6A, 0xE0, 0xC3, 0x94, 0x40, 0x40, 0x02, - 0x41, 0xAF, 0xE0, 0xFF, 0x24, 0x79, 0xF5, 0x82, - 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, 0x90, 0x81, - 0x6C, 0xF0, 0xE0, 0xFE, 0x54, 0xF0, 0xC4, 0x54, - 0x0F, 0xFD, 0x90, 0x81, 0x6B, 0xF0, 0xEE, 0x54, - 0x0F, 0xFE, 0xA3, 0xF0, 0x74, 0x7A, 0x2F, 0xF5, - 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, 0x90, - 0x81, 0x6D, 0xF0, 0xFC, 0xEE, 0xFE, 0xEC, 0xFB, - 0xEB, 0xFF, 0x90, 0x81, 0x72, 0xEE, 0xF0, 0xA3, - 0xEF, 0xF0, 0xED, 0x12, 0x45, 0x28, 0x68, 0x8B, - 0x00, 0x68, 0xC2, 0x01, 0x69, 0x73, 0x02, 0x6A, - 0xA0, 0x03, 0x69, 0x8E, 0x04, 0x69, 0xAF, 0x05, - 0x69, 0xAF, 0x06, 0x69, 0xAF, 0x07, 0x69, 0xAF, - 0x08, 0x6A, 0x33, 0x09, 0x6A, 0x69, 0x0A, 0x00, - 0x00, 0x6A, 0xAF, 0x90, 0x81, 0x6A, 0xE0, 0xFD, - 0x24, 0x7C, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, - 0x83, 0xE0, 0xFE, 0x74, 0x7B, 0x2D, 0xF5, 0x82, - 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, 0xFD, 0xED, - 0xFF, 0x90, 0x81, 0x74, 0xEE, 0xF0, 0xFC, 0xA3, - 0xEF, 0xF0, 0x90, 0x81, 0x6D, 0xE0, 0xFF, 0x12, - 0x2F, 0x96, 0x90, 0x81, 0x68, 0x74, 0x02, 0xF0, - 0x41, 0xA0, 0x90, 0x81, 0x6A, 0xE0, 0x24, 0x7C, - 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, - 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x08, 0x12, - 0x20, 0xBB, 0xA8, 0x04, 0xA9, 0x05, 0xAA, 0x06, - 0xAB, 0x07, 0x90, 0x81, 0x6A, 0xE0, 0x24, 0x7B, - 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, - 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x12, 0x44, 0xCC, - 0xC0, 0x04, 0xC0, 0x05, 0xC0, 0x06, 0xC0, 0x07, - 0x90, 0x81, 0x6A, 0xE0, 0x24, 0x7D, 0xF5, 0x82, - 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, 0xFF, 0xE4, - 0xFC, 0xFD, 0xFE, 0x78, 0x10, 0x12, 0x20, 0xBB, - 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, 0x00, - 0x12, 0x44, 0xCC, 0xC0, 0x04, 0xC0, 0x05, 0xC0, - 0x06, 0xC0, 0x07, 0x90, 0x81, 0x6A, 0xE0, 0x24, - 0x7E, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, - 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x18, - 0x12, 0x20, 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, - 0x01, 0xD0, 0x00, 0x12, 0x44, 0xCC, 0x90, 0x81, - 0x6E, 0x12, 0x20, 0xCE, 0x90, 0x81, 0x6E, 0x12, - 0x44, 0xD9, 0x90, 0x85, 0x96, 0x12, 0x20, 0xCE, - 0x90, 0x81, 0x72, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, - 0x12, 0x2E, 0xE4, 0x90, 0x81, 0x68, 0x74, 0x04, - 0xF0, 0x41, 0xA0, 0x90, 0x81, 0x6D, 0xE0, 0xFD, - 0x90, 0x81, 0x6A, 0xE0, 0x24, 0x7B, 0xF5, 0x82, - 0xE4, 0x34, 0x81, 0xF5, 0x83, 0xE0, 0xFB, 0xE4, - 0xFF, 0x12, 0x30, 0xC7, 0x80, 0x19, 0x90, 0x81, - 0x6D, 0xE0, 0xFD, 0x90, 0x81, 0x6A, 0xE0, 0x24, - 0x7B, 0xF5, 0x82, 0xE4, 0x34, 0x81, 0xF5, 0x83, - 0xE0, 0xFB, 0xE4, 0xFF, 0x12, 0x30, 0x6A, 0x90, - 0x81, 0x68, 0x74, 0x01, 0xF0, 0x41, 0xA0, 0x90, - 0x81, 0x68, 0x74, 0x02, 0xF0, 0x90, 0x81, 0x6A, - 0xE0, 0x24, 0x7C, 0xF5, 0x82, 0xE4, 0x34, 0x81, - 0xF5, 0x83, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, - 0x78, 0x08, 0x12, 0x20, 0xBB, 0xA8, 0x04, 0xA9, - 0x05, 0xAA, 0x06, 0xAB, 0x07, 0x90, 0x81, 0x6A, - 0xE0, 0x24, 0x7B, 0xF5, 0x82, 0xE4, 0x34, 0x81, - 0xF5, 0x83, 0xE0, 0xFF, 0xE4, 0xFC, 0xFD, 0xFE, - 0x12, 0x44, 0xCC, 0xC0, 0x04, 0xC0, 0x05, 0xC0, - 0x06, 0xC0, 0x07, 0x90, 0x81, 0x6C, 0xE0, 0xFF, - 0xE4, 0xFC, 0xFD, 0xFE, 0x78, 0x10, 0x12, 0x20, - 0xBB, 0xD0, 0x03, 0xD0, 0x02, 0xD0, 0x01, 0xD0, - 0x00, 0x12, 0x44, 0xCC, 0x90, 0x81, 0x6E, 0x12, - 0x20, 0xCE, 0x90, 0x81, 0x6B, 0xE0, 0x24, 0xFB, - 0xFF, 0xC0, 0x07, 0x90, 0x81, 0x6E, 0x12, 0x44, - 0xD9, 0x90, 0x81, 0xF9, 0x12, 0x20, 0xCE, 0x90, - 0x81, 0x6D, 0xE0, 0xFD, 0xD0, 0x07, 0x12, 0x55, - 0x1C, 0x80, 0x6D, 0x90, 0x81, 0x68, 0x74, 0x01, - 0xF0, 0x90, 0x81, 0x6A, 0xE0, 0x24, 0x7B, 0xF9, - 0xE4, 0x34, 0x81, 0x75, 0x13, 0x01, 0xF5, 0x14, - 0x89, 0x15, 0x75, 0x16, 0x01, 0x7B, 0xFE, 0x7A, - 0x80, 0x79, 0x33, 0x12, 0x2B, 0xED, 0x90, 0x81, - 0x6D, 0xE0, 0xFF, 0x90, 0x81, 0x6C, 0xE0, 0xFD, - 0xE4, 0x90, 0x81, 0xBC, 0xF0, 0x7B, 0x04, 0x80, - 0x34, 0x90, 0x81, 0x68, 0x74, 0x04, 0xF0, 0x90, - 0x81, 0x6A, 0xE0, 0x24, 0x7B, 0xF9, 0xE4, 0x34, - 0x81, 0x75, 0x13, 0x01, 0xF5, 0x14, 0x89, 0x15, - 0x75, 0x16, 0x04, 0x7B, 0xFE, 0x7A, 0x80, 0x79, - 0x33, 0x12, 0x2B, 0xED, 0x90, 0x81, 0x6D, 0xE0, - 0xFF, 0x90, 0x81, 0x6C, 0xE0, 0xFD, 0xE4, 0x90, - 0x81, 0xBC, 0xF0, 0x7B, 0x06, 0x12, 0x63, 0xE1, - 0x90, 0x81, 0x68, 0xE0, 0x24, 0x02, 0xFF, 0x90, - 0x81, 0x6A, 0xE0, 0x2F, 0xF0, 0x01, 0x17, 0x22, - 0x90, 0x02, 0x09, 0xE0, 0xFD, 0x12, 0x1F, 0xA4, - 0xFE, 0xAF, 0x05, 0xED, 0x2E, 0x90, 0x80, 0x3D, - 0xF0, 0x90, 0x00, 0x01, 0x12, 0x1F, 0xBD, 0xFF, - 0xED, 0x2F, 0x90, 0x80, 0x3E, 0xF0, 0x90, 0x00, - 0x02, 0x12, 0x1F, 0xBD, 0xFF, 0xED, 0x2F, 0x90, - 0x80, 0x3F, 0xF0, 0x90, 0x00, 0x03, 0x12, 0x1F, - 0xBD, 0xFF, 0xED, 0x2F, 0x90, 0x80, 0x40, 0xF0, - 0x90, 0x00, 0x04, 0x12, 0x1F, 0xBD, 0xFF, 0xAE, - 0x05, 0xED, 0x2F, 0x90, 0x80, 0x41, 0xF0, 0x22, - 0x90, 0x00, 0x02, 0x12, 0x1F, 0xBD, 0xFF, 0x30, - 0xE0, 0x26, 0x12, 0x1F, 0xA4, 0x90, 0x81, 0x38, - 0xF0, 0x90, 0x00, 0x01, 0x12, 0x1F, 0xBD, 0x90, - 0x81, 0x39, 0xF0, 0xEF, 0x54, 0xFE, 0xFF, 0xA3, - 0xE0, 0x54, 0x01, 0x4F, 0xF0, 0x90, 0x00, 0x03, - 0x12, 0x1F, 0xBD, 0x90, 0x81, 0x3B, 0xF0, 0x22, - 0x90, 0x81, 0x38, 0x74, 0x01, 0xF0, 0xA3, 0x74, - 0x05, 0xF0, 0xA3, 0xE0, 0x54, 0x01, 0x44, 0x28, - 0xF0, 0xA3, 0x74, 0x05, 0xF0, 0x22, 0x12, 0x1F, - 0xA4, 0x90, 0x81, 0x3E, 0xF0, 0x90, 0x81, 0x3E, - 0xE0, 0x90, 0x01, 0xE7, 0xF0, 0x22, 0x12, 0x1F, - 0xA4, 0x90, 0x81, 0x4A, 0xF0, 0x90, 0x00, 0x01, - 0x12, 0x1F, 0xBD, 0x90, 0x81, 0x4B, 0xF0, 0x22, - 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, - 0x81, 0xFD, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0xE4, - 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0x81, 0xFD, 0xE0, - 0xFE, 0xA3, 0xE0, 0xF5, 0x82, 0x8E, 0x83, 0xE0, - 0x60, 0x2D, 0xC3, 0x90, 0x82, 0x00, 0xE0, 0x94, - 0xE8, 0x90, 0x81, 0xFF, 0xE0, 0x94, 0x03, 0x40, - 0x0B, 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x80, 0xF0, - 0x7F, 0x00, 0x80, 0x15, 0x90, 0x81, 0xFF, 0xE4, - 0x75, 0xF0, 0x01, 0x12, 0x44, 0xA9, 0x7F, 0x0A, - 0x7E, 0x00, 0x12, 0x32, 0xAA, 0x80, 0xC5, 0x7F, - 0x01, 0xD0, 0xD0, 0x92, 0xAF, 0x22, 0xD3, 0x10, - 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x81, 0xD1, - 0x12, 0x45, 0x1F, 0x90, 0x82, 0x0A, 0xE0, 0xFF, - 0x04, 0xF0, 0x90, 0x00, 0x01, 0xEF, 0x12, 0x1F, - 0xFC, 0x7F, 0xAF, 0x7E, 0x01, 0x71, 0x60, 0xEF, - 0x60, 0x3A, 0x90, 0x81, 0xD1, 0x12, 0x45, 0x16, - 0x8B, 0x13, 0x8A, 0x14, 0x89, 0x15, 0x90, 0x00, - 0x0E, 0x12, 0x1F, 0xBD, 0x24, 0x02, 0xF5, 0x16, - 0x7B, 0x01, 0x7A, 0x01, 0x79, 0xA0, 0x12, 0x2B, - 0xED, 0x90, 0x81, 0xD1, 0x12, 0x45, 0x16, 0x90, - 0x00, 0x0E, 0x12, 0x1F, 0xBD, 0x90, 0x01, 0xAE, - 0xF0, 0xA3, 0x74, 0xFF, 0xF0, 0x90, 0x01, 0xCB, - 0xE0, 0x64, 0x80, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, - 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, - 0xE4, 0xFF, 0x90, 0x80, 0xD9, 0xE0, 0xFE, 0x90, - 0x80, 0xD8, 0xE0, 0xFD, 0xB5, 0x06, 0x04, 0x7E, - 0x01, 0x80, 0x02, 0x7E, 0x00, 0xEE, 0x64, 0x01, - 0x60, 0x32, 0x90, 0x01, 0xAF, 0xE0, 0x70, 0x13, - 0xED, 0x75, 0xF0, 0x0F, 0xA4, 0x24, 0x42, 0xF9, - 0x74, 0x80, 0x35, 0xF0, 0xFA, 0x7B, 0x01, 0x71, - 0xB6, 0x7F, 0x01, 0xEF, 0x60, 0x16, 0x90, 0x80, - 0xD8, 0xE0, 0x04, 0xF0, 0xE0, 0x7F, 0x00, 0xB4, - 0x0A, 0x02, 0x7F, 0x01, 0xEF, 0x60, 0x05, 0xE4, - 0x90, 0x80, 0xD8, 0xF0, 0xD0, 0xD0, 0x92, 0xAF, - 0x22, 0x8F, 0x0D, 0x22, 0x8F, 0x0E, 0x22, 0x22, - 0x90, 0x01, 0x34, 0xE0, 0x55, 0x3D, 0xF5, 0x41, - 0xA3, 0xE0, 0x55, 0x3E, 0xF5, 0x42, 0xA3, 0xE0, - 0x55, 0x3F, 0xF5, 0x43, 0xA3, 0xE0, 0x55, 0x40, - 0xF5, 0x44, 0x90, 0x01, 0x34, 0xE5, 0x41, 0xF0, - 0xA3, 0xE5, 0x42, 0xF0, 0xA3, 0xE5, 0x43, 0xF0, - 0xA3, 0xE5, 0x44, 0xF0, 0x22, 0x90, 0x01, 0x3C, - 0xE0, 0x55, 0x45, 0xF5, 0x49, 0xA3, 0xE0, 0x55, - 0x46, 0xF5, 0x4A, 0xA3, 0xE0, 0x55, 0x47, 0xF5, - 0x4B, 0xA3, 0xE0, 0x55, 0x48, 0xF5, 0x4C, 0x90, - 0x01, 0x3C, 0xE5, 0x49, 0xF0, 0xA3, 0xE5, 0x4A, - 0xF0, 0xA3, 0xE5, 0x4B, 0xF0, 0xA3, 0xE5, 0x4C, - 0xF0, 0x53, 0x91, 0xDF, 0x22, 0x90, 0x81, 0x1F, - 0xE0, 0x30, 0xE0, 0x05, 0xE4, 0xA3, 0xF0, 0xA3, - 0xF0, 0x22, 0x90, 0x80, 0xDE, 0xE0, 0x64, 0x01, - 0x70, 0x19, 0x90, 0x81, 0x27, 0xE0, 0x60, 0x13, - 0x90, 0x01, 0x57, 0xE4, 0xF0, 0x90, 0x01, 0x3C, - 0x74, 0x02, 0x12, 0x4F, 0xF4, 0x90, 0x01, 0x57, - 0x74, 0x05, 0xF0, 0x22, 0x90, 0x80, 0xDE, 0xE0, - 0x64, 0x01, 0x70, 0x26, 0x90, 0x81, 0x27, 0xE0, - 0x60, 0x20, 0x90, 0x01, 0x57, 0xE4, 0xF0, 0x90, - 0x01, 0x3C, 0x74, 0x02, 0xF0, 0x90, 0x81, 0x24, - 0xE0, 0x54, 0xFB, 0xF0, 0x90, 0x81, 0x2B, 0xE0, - 0x54, 0xFD, 0xF0, 0x54, 0x07, 0x70, 0x03, 0x12, - 0x47, 0x2A, 0x22, 0x90, 0x80, 0xDE, 0xE0, 0xB4, - 0x01, 0x14, 0x90, 0x81, 0x27, 0xE0, 0x60, 0x0E, - 0x90, 0x81, 0x26, 0xE0, 0x54, 0x0F, 0x64, 0x02, - 0x60, 0x02, 0x80, 0x03, 0xD1, 0x7F, 0x22, 0x90, - 0x04, 0x1D, 0xE0, 0x70, 0x13, 0x90, 0x80, 0x3E, - 0xE0, 0xFF, 0xE4, 0xFD, 0xB1, 0x69, 0x8E, 0x4E, - 0x8F, 0x4F, 0x90, 0x04, 0x1F, 0x74, 0x20, 0xF0, - 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, - 0x90, 0x82, 0x0E, 0xED, 0xF0, 0x90, 0x82, 0x0D, - 0xEF, 0xF0, 0xE4, 0xFD, 0xFC, 0xF1, 0x37, 0x7C, - 0x00, 0xAD, 0x07, 0x90, 0x82, 0x0D, 0xE0, 0x90, - 0x04, 0x25, 0xF0, 0x90, 0x82, 0x0E, 0xE0, 0x60, - 0x0E, 0x74, 0x0F, 0x2F, 0xF5, 0x82, 0xE4, 0x34, - 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x80, 0xF0, 0xAF, - 0x05, 0x74, 0x08, 0x2F, 0xF5, 0x82, 0xE4, 0x34, - 0xFC, 0xF5, 0x83, 0xE4, 0xF0, 0x74, 0x09, 0x2F, - 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, - 0x54, 0xF0, 0xF0, 0x74, 0x21, 0x2D, 0xF5, 0x82, - 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x54, 0xF7, - 0xF0, 0xAE, 0x04, 0xAF, 0x05, 0xD0, 0xD0, 0x92, - 0xAF, 0x22, 0x8F, 0x4E, 0xF1, 0x4B, 0xBF, 0x01, - 0x18, 0x90, 0x80, 0x40, 0xE0, 0xFF, 0x7D, 0x01, - 0xB1, 0x69, 0xAD, 0x07, 0xAC, 0x06, 0xAF, 0x4E, - 0x12, 0x4F, 0x82, 0x90, 0x04, 0x1F, 0x74, 0x20, - 0xF0, 0x22, 0x90, 0x06, 0xA9, 0xE0, 0x90, 0x81, - 0x4C, 0xF0, 0xE0, 0xFD, 0x54, 0xC0, 0x70, 0x09, - 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFE, 0xF0, 0x80, - 0x72, 0xED, 0x30, 0xE6, 0x4B, 0x90, 0x81, 0x27, - 0xE0, 0x64, 0x02, 0x70, 0x2A, 0x90, 0x81, 0x24, - 0xE0, 0xFF, 0xC3, 0x13, 0x20, 0xE0, 0x09, 0x90, - 0x81, 0x2B, 0xE0, 0x44, 0x01, 0xF0, 0x80, 0x28, - 0x90, 0x81, 0x26, 0xE0, 0x54, 0x0F, 0x64, 0x01, - 0x70, 0x2D, 0x90, 0x81, 0x2B, 0xE0, 0x44, 0x04, - 0xF0, 0x7F, 0x01, 0xB1, 0xD2, 0x80, 0x20, 0x90, - 0x81, 0x2B, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x81, - 0x26, 0xE0, 0x54, 0x0F, 0x64, 0x02, 0x60, 0x04, - 0xB1, 0x4F, 0x80, 0x0B, 0xD1, 0x7F, 0x80, 0x07, - 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFE, 0xF0, 0x90, - 0x81, 0x4C, 0xE0, 0x90, 0x81, 0x2B, 0x30, 0xE7, - 0x11, 0x12, 0x4F, 0xF1, 0x90, 0x01, 0x57, 0x74, - 0x05, 0xF0, 0x90, 0x81, 0x24, 0xE0, 0x44, 0x04, - 0xF0, 0x22, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, - 0x01, 0x5F, 0xE4, 0xF0, 0x90, 0x01, 0x3C, 0x74, - 0x08, 0xF0, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x3A, - 0xE0, 0xC3, 0x13, 0x54, 0x7F, 0xF5, 0x1E, 0xE4, - 0xFB, 0xFD, 0x7F, 0x5C, 0x7E, 0x01, 0x12, 0x50, - 0x05, 0x90, 0x01, 0x5F, 0x74, 0x05, 0xF0, 0x90, - 0x06, 0x92, 0x74, 0x02, 0xF0, 0x90, 0x81, 0x24, - 0xE0, 0x44, 0x10, 0xF0, 0x90, 0x81, 0x2A, 0xE0, - 0x64, 0x0C, 0x60, 0x0C, 0xE4, 0xFD, 0x7F, 0x0C, - 0x12, 0x47, 0x3D, 0xE4, 0xFF, 0x12, 0x4F, 0x0D, - 0x22, 0xE4, 0x90, 0x81, 0x4C, 0xF0, 0x90, 0x06, - 0xA9, 0xE0, 0x90, 0x81, 0x4C, 0xF0, 0xE0, 0x54, - 0xC0, 0x70, 0x0D, 0x90, 0x81, 0x2B, 0xE0, 0x54, - 0xFE, 0xF0, 0x54, 0xFD, 0xF0, 0x02, 0x47, 0x2A, - 0x90, 0x81, 0x4C, 0xE0, 0x30, 0xE6, 0x21, 0x90, - 0x81, 0x27, 0xE0, 0x64, 0x01, 0x70, 0x20, 0x90, - 0x81, 0x2B, 0xE0, 0x44, 0x01, 0xF0, 0x90, 0x81, - 0x26, 0xE0, 0x54, 0x0F, 0x64, 0x02, 0x60, 0x04, - 0xB1, 0x4F, 0x80, 0x0B, 0xD1, 0x7F, 0x80, 0x07, - 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFE, 0xF0, 0x90, - 0x81, 0x4C, 0xE0, 0x90, 0x81, 0x2B, 0x30, 0xE7, - 0x11, 0x12, 0x4F, 0xF1, 0x90, 0x01, 0x57, 0x74, - 0x05, 0xF0, 0x90, 0x81, 0x24, 0xE0, 0x44, 0x04, - 0xF0, 0x22, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0xE4, - 0xFE, 0xEF, 0xC3, 0x13, 0xFD, 0xEF, 0x30, 0xE0, - 0x02, 0x7E, 0x80, 0x90, 0xFD, 0x10, 0xED, 0xF0, - 0xAF, 0x06, 0x22, 0xD3, 0x10, 0xAF, 0x01, 0xC3, - 0xC0, 0xD0, 0x90, 0x04, 0x1D, 0xE0, 0x60, 0x1A, - 0x90, 0x05, 0x22, 0xE0, 0x54, 0x90, 0x60, 0x07, - 0x90, 0x01, 0xC0, 0xE0, 0x44, 0x08, 0xF0, 0x90, - 0x01, 0xC6, 0xE0, 0x30, 0xE1, 0xE4, 0x7F, 0x00, - 0x80, 0x02, 0x7F, 0x01, 0xD0, 0xD0, 0x92, 0xAF, - 0x22, 0x90, 0x81, 0x27, 0xE0, 0x60, 0x03, 0x12, - 0x73, 0xE1, 0x90, 0x81, 0x3F, 0xE0, 0x30, 0xE0, - 0x03, 0x12, 0x49, 0xDD, 0x22, 0x90, 0x81, 0x27, - 0xE0, 0x60, 0x35, 0x90, 0x06, 0x92, 0xE0, 0x30, - 0xE1, 0x24, 0xE4, 0xF5, 0x1D, 0x90, 0x81, 0x3A, - 0xE0, 0xC3, 0x13, 0x54, 0x7F, 0xF5, 0x1E, 0xE4, - 0xFB, 0xFD, 0x7F, 0x5C, 0x7E, 0x01, 0x12, 0x50, - 0x05, 0x90, 0x01, 0x5F, 0x74, 0x05, 0xF0, 0x90, - 0x06, 0x92, 0x74, 0x02, 0xF0, 0x22, 0x90, 0x81, - 0x24, 0xE0, 0x54, 0xEF, 0xF0, 0x12, 0x47, 0x2A, - 0x22, 0x12, 0x71, 0x48, 0x90, 0x81, 0x4D, 0xEF, - 0xF0, 0x90, 0x81, 0x24, 0x30, 0xE0, 0x06, 0xE0, - 0x44, 0x01, 0xF0, 0x80, 0x04, 0xE0, 0x54, 0xFE, - 0xF0, 0x90, 0x81, 0x4D, 0xE0, 0x30, 0xE6, 0x11, - 0x90, 0x01, 0x2F, 0xE0, 0x30, 0xE7, 0x04, 0xE4, - 0xF0, 0x80, 0x06, 0x90, 0x01, 0x2F, 0x74, 0x80, - 0xF0, 0x90, 0x81, 0x24, 0xE0, 0x30, 0xE0, 0x1A, - 0x90, 0x81, 0x32, 0xE4, 0xF0, 0xA3, 0x74, 0x07, - 0xF0, 0x90, 0x81, 0x32, 0xA3, 0xE0, 0x90, 0x05, - 0x58, 0xF0, 0x90, 0x04, 0xEC, 0xE0, 0x54, 0xDD, - 0xF0, 0x22, 0x90, 0x04, 0xEC, 0xE0, 0x44, 0x22, - 0xF0, 0x22, 0x90, 0x81, 0x4A, 0xE0, 0x60, 0x0F, - 0xE4, 0xF0, 0x90, 0x05, 0x53, 0xE0, 0x44, 0x01, - 0xF0, 0x90, 0x05, 0xFD, 0xE0, 0x04, 0xF0, 0x22, - 0x90, 0x81, 0x24, 0xE0, 0xFF, 0xC4, 0x13, 0x13, - 0x54, 0x03, 0x30, 0xE0, 0x27, 0xEF, 0x54, 0xBF, - 0xF0, 0x90, 0x04, 0xE0, 0xE0, 0x90, 0x81, 0x25, - 0x30, 0xE0, 0x06, 0xE0, 0x44, 0x01, 0xF0, 0x80, - 0x10, 0xE0, 0x54, 0xFE, 0xF0, 0x90, 0x01, 0xB9, - 0x74, 0x01, 0xF0, 0x90, 0x01, 0xB8, 0x74, 0x04, - 0xF0, 0x12, 0x47, 0x2A, 0xE4, 0xFF, 0x90, 0x81, - 0x45, 0xE0, 0x30, 0xE0, 0x48, 0x90, 0x81, 0x49, - 0xE0, 0xFD, 0x60, 0x41, 0x74, 0x01, 0x7E, 0x00, - 0xA8, 0x07, 0x08, 0x80, 0x05, 0xC3, 0x33, 0xCE, - 0x33, 0xCE, 0xD8, 0xF9, 0xFF, 0x90, 0x04, 0xE0, - 0xE0, 0xFB, 0xEF, 0x5B, 0x60, 0x06, 0xE4, 0x90, - 0x81, 0x49, 0xF0, 0x22, 0x90, 0x81, 0x47, 0xE0, - 0xD3, 0x9D, 0x50, 0x10, 0x90, 0x01, 0xC7, 0x74, - 0x10, 0xF0, 0x11, 0xBE, 0x90, 0x81, 0x45, 0xE0, - 0x54, 0xFE, 0xF0, 0x22, 0x12, 0x4F, 0x0B, 0x90, - 0x81, 0x49, 0xE0, 0x04, 0xF0, 0x22, 0x90, 0x80, - 0x3C, 0xE0, 0x64, 0x02, 0x60, 0x07, 0x90, 0x06, - 0x90, 0xE0, 0x44, 0x01, 0xF0, 0x22, 0x90, 0x81, - 0x24, 0xE0, 0xFF, 0xC4, 0x13, 0x13, 0x13, 0x54, - 0x01, 0x30, 0xE0, 0x2C, 0xEF, 0x54, 0x7F, 0xF0, - 0x90, 0x04, 0xE0, 0xE0, 0x90, 0x81, 0x25, 0x30, - 0xE1, 0x06, 0xE0, 0x44, 0x02, 0xF0, 0x80, 0x0F, - 0xE0, 0x54, 0xFD, 0xF0, 0x90, 0x01, 0xB9, 0x74, - 0x01, 0xF0, 0x90, 0x01, 0xB8, 0x04, 0xF0, 0x90, - 0x81, 0x27, 0xE0, 0x60, 0x03, 0x12, 0x47, 0x2A, - 0x7F, 0x01, 0x01, 0x6E, 0xC3, 0xEE, 0x94, 0x01, - 0x40, 0x0A, 0x0D, 0xED, 0x13, 0x90, 0xFD, 0x10, - 0xF0, 0xE4, 0x2F, 0xFF, 0x22, 0xC3, 0xEE, 0x94, - 0x01, 0x40, 0x24, 0x90, 0xFD, 0x11, 0xE0, 0x6D, - 0x70, 0x1A, 0x90, 0x01, 0x17, 0xE0, 0xB5, 0x05, - 0x0D, 0x90, 0x01, 0xE4, 0x74, 0x77, 0xF0, 0x90, - 0xFD, 0x11, 0xE4, 0xF0, 0x80, 0x06, 0xED, 0x04, - 0x90, 0xFD, 0x11, 0xF0, 0xE4, 0x2F, 0xFF, 0x22, - 0xE4, 0x90, 0x81, 0x4E, 0xF0, 0xA3, 0xF0, 0xA3, - 0xF0, 0x90, 0x00, 0x83, 0xE0, 0x90, 0x81, 0x4E, - 0xF0, 0x90, 0x00, 0x83, 0xE0, 0xFE, 0x90, 0x81, - 0x4E, 0xE0, 0xFF, 0xB5, 0x06, 0x01, 0x22, 0xC3, - 0x90, 0x81, 0x50, 0xE0, 0x94, 0x64, 0x90, 0x81, - 0x4F, 0xE0, 0x94, 0x00, 0x40, 0x0D, 0x90, 0x01, - 0xC0, 0xE0, 0x44, 0x40, 0xF0, 0x90, 0x81, 0x4E, - 0xE0, 0xFF, 0x22, 0x90, 0x81, 0x4F, 0xE4, 0x75, - 0xF0, 0x01, 0x12, 0x44, 0xA9, 0x80, 0xC2, 0x74, - 0x45, 0x2F, 0xF8, 0xE6, 0xFE, 0xED, 0xF4, 0x5E, - 0xFE, 0xF6, 0x74, 0x38, 0x2F, 0xF5, 0x82, 0xE4, - 0x34, 0x01, 0xF5, 0x83, 0xEE, 0xF0, 0x22, 0xD3, - 0x10, 0xAF, 0x01, 0xC3, 0xC0, 0xD0, 0x90, 0x82, - 0x12, 0xED, 0xF0, 0x90, 0x82, 0x11, 0xEF, 0xF0, - 0xD3, 0x94, 0x07, 0x50, 0x70, 0xE0, 0xFF, 0x74, - 0x01, 0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, 0x33, - 0xD8, 0xFC, 0xF4, 0xFF, 0x90, 0x00, 0x47, 0xE0, - 0x5F, 0xFD, 0x7F, 0x47, 0x12, 0x32, 0x1E, 0x90, - 0x82, 0x11, 0xE0, 0xFF, 0x74, 0x01, 0xA8, 0x07, - 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, 0xFF, - 0x90, 0x00, 0x46, 0xE0, 0x4F, 0xFD, 0x7F, 0x46, - 0x12, 0x32, 0x1E, 0x90, 0x82, 0x12, 0xE0, 0x60, - 0x18, 0x90, 0x82, 0x11, 0xE0, 0xFF, 0x74, 0x01, - 0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, - 0xFC, 0xFF, 0x90, 0x00, 0x45, 0xE0, 0x4F, 0x80, - 0x17, 0x90, 0x82, 0x11, 0xE0, 0xFF, 0x74, 0x01, - 0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, - 0xFC, 0xF4, 0xFF, 0x90, 0x00, 0x45, 0xE0, 0x5F, - 0xFD, 0x7F, 0x45, 0x80, 0x7E, 0x90, 0x82, 0x11, - 0xE0, 0x24, 0xF8, 0xF0, 0xE0, 0x24, 0x04, 0xFF, - 0x74, 0x01, 0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, - 0x33, 0xD8, 0xFC, 0xF4, 0xFF, 0x90, 0x00, 0x43, - 0xE0, 0x5F, 0xFD, 0x7F, 0x43, 0x12, 0x32, 0x1E, - 0x90, 0x82, 0x11, 0xE0, 0xFF, 0x74, 0x01, 0xA8, - 0x07, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, 0xFC, - 0xFF, 0x90, 0x00, 0x43, 0xE0, 0x4F, 0xFD, 0x7F, - 0x43, 0x12, 0x32, 0x1E, 0x90, 0x82, 0x12, 0xE0, - 0x60, 0x1D, 0x90, 0x82, 0x11, 0xE0, 0x24, 0x04, - 0xFF, 0x74, 0x01, 0xA8, 0x07, 0x08, 0x80, 0x02, - 0xC3, 0x33, 0xD8, 0xFC, 0xFF, 0x90, 0x00, 0x42, - 0xE0, 0x4F, 0xFD, 0x7F, 0x42, 0x80, 0x1C, 0x90, - 0x82, 0x11, 0xE0, 0x24, 0x04, 0xFF, 0x74, 0x01, - 0xA8, 0x07, 0x08, 0x80, 0x02, 0xC3, 0x33, 0xD8, - 0xFC, 0xF4, 0xFF, 0x90, 0x00, 0x42, 0xE0, 0x5F, - 0xFD, 0x7F, 0x42, 0x12, 0x32, 0x1E, 0xD0, 0xD0, - 0x92, 0xAF, 0x22, 0x90, 0x81, 0x24, 0xE0, 0x54, - 0xFB, 0xF0, 0xE4, 0x90, 0x81, 0x30, 0xF0, 0x90, - 0x81, 0x2B, 0xF0, 0x22, 0xEF, 0x24, 0xFE, 0x60, - 0x0C, 0x04, 0x70, 0x28, 0x90, 0x81, 0x2D, 0x74, - 0x01, 0xF0, 0xA3, 0xF0, 0x22, 0xED, 0x70, 0x0A, - 0x90, 0x81, 0x3B, 0xE0, 0x90, 0x81, 0x2D, 0xF0, - 0x80, 0x05, 0x90, 0x81, 0x2D, 0xED, 0xF0, 0x90, - 0x81, 0x2D, 0xE0, 0xA3, 0xF0, 0x90, 0x81, 0x25, - 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x12, 0x4E, 0xAB, - 0xEF, 0x64, 0x01, 0x60, 0x08, 0x90, 0x01, 0xB8, - 0x74, 0x01, 0xF0, 0x80, 0x67, 0x90, 0x81, 0x2B, - 0xE0, 0xFF, 0x54, 0x03, 0x60, 0x08, 0x90, 0x01, - 0xB8, 0x74, 0x02, 0xF0, 0x80, 0x56, 0x90, 0x81, - 0x29, 0xE0, 0xFE, 0xE4, 0xC3, 0x9E, 0x50, 0x08, - 0x90, 0x01, 0xB8, 0x74, 0x04, 0xF0, 0x80, 0x44, - 0xEF, 0x30, 0xE2, 0x08, 0x90, 0x01, 0xB8, 0x74, - 0x08, 0xF0, 0x80, 0x38, 0x90, 0x81, 0x2B, 0xE0, - 0x30, 0xE4, 0x08, 0x90, 0x01, 0xB8, 0x74, 0x10, - 0xF0, 0x80, 0x29, 0x90, 0x81, 0x25, 0xE0, 0x13, - 0x13, 0x54, 0x3F, 0x20, 0xE0, 0x08, 0x90, 0x01, - 0xB8, 0x74, 0x20, 0xF0, 0x80, 0x16, 0x90, 0x81, - 0x3E, 0xE0, 0x60, 0x08, 0x90, 0x01, 0xB8, 0x74, - 0x80, 0xF0, 0x80, 0x08, 0x90, 0x01, 0xB8, 0xE4, - 0xF0, 0x7F, 0x01, 0x22, 0x90, 0x01, 0xB9, 0x74, - 0x04, 0xF0, 0x7F, 0x00, 0x22, 0xEF, 0x60, 0x42, - 0x90, 0x80, 0xDE, 0xE0, 0x64, 0x01, 0x70, 0x3A, - 0x90, 0x81, 0x25, 0xE0, 0x54, 0xFE, 0xF0, 0x90, - 0x05, 0x22, 0x74, 0x0F, 0xF0, 0x90, 0x06, 0x04, - 0xE0, 0x54, 0xBF, 0xF0, 0xE4, 0xFF, 0x12, 0x4F, - 0x0D, 0xBF, 0x01, 0x12, 0x90, 0x81, 0x24, 0xE0, - 0x44, 0x40, 0xF0, 0x90, 0x81, 0x2A, 0x74, 0x06, - 0xF0, 0x90, 0x81, 0x23, 0xF0, 0x22, 0x90, 0x01, - 0xB9, 0x74, 0x01, 0xF0, 0x90, 0x01, 0xB8, 0x74, - 0x08, 0xF0, 0x22, 0x90, 0x05, 0x22, 0x74, 0x6F, - 0xF0, 0x90, 0x05, 0x27, 0xE0, 0x54, 0xBF, 0xF0, - 0x90, 0x81, 0x2A, 0x74, 0x02, 0xF0, 0x90, 0x81, - 0x23, 0xF0, 0x22, 0x12, 0x54, 0x65, 0x90, 0x81, - 0x2A, 0x74, 0x0C, 0xF0, 0x90, 0x81, 0x23, 0xF0, - 0x22, 0x90, 0x81, 0x24, 0xE0, 0xFF, 0x13, 0x13, - 0x54, 0x3F, 0x30, 0xE0, 0x11, 0xEF, 0x54, 0xFB, - 0xF0, 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFD, 0xF0, - 0x54, 0x07, 0x70, 0x42, 0x80, 0x3D, 0x90, 0x81, - 0x30, 0xE0, 0x04, 0xF0, 0x90, 0x81, 0x2B, 0xE0, - 0x54, 0xEF, 0xF0, 0x90, 0x81, 0x30, 0xE0, 0xFF, - 0xB4, 0x01, 0x02, 0x80, 0x04, 0xEF, 0xB4, 0x02, - 0x06, 0x90, 0x05, 0x58, 0xE0, 0x04, 0xF0, 0x90, - 0x81, 0x38, 0xE0, 0xFF, 0x90, 0x81, 0x30, 0xE0, - 0xD3, 0x9F, 0x40, 0x0F, 0x90, 0x80, 0xDE, 0xE0, - 0xB4, 0x01, 0x0B, 0x90, 0x81, 0x25, 0xE0, 0x54, - 0xFB, 0xF0, 0x22, 0x12, 0x47, 0x2A, 0x22, 0x22, - 0x90, 0x05, 0x2B, 0xE0, 0x7F, 0x00, 0x30, 0xE7, - 0x02, 0x7F, 0x01, 0x22, 0x90, 0x05, 0x22, 0x74, - 0xFF, 0xF0, 0x90, 0x05, 0x27, 0xE0, 0x44, 0x40, - 0xF0, 0x90, 0x81, 0x22, 0x74, 0x03, 0xF0, 0x22, - 0x90, 0x05, 0x27, 0xE0, 0x44, 0x40, 0xF0, 0x12, - 0x49, 0xDD, 0x90, 0x81, 0x22, 0x74, 0x02, 0xF0, - 0x22, 0x12, 0x49, 0xE3, 0x90, 0x81, 0x22, 0x74, - 0x02, 0xF0, 0x22, 0x90, 0x05, 0x22, 0x74, 0x6F, - 0xF0, 0x90, 0x05, 0x27, 0xE0, 0x54, 0xBF, 0xF0, - 0x90, 0x81, 0x22, 0x74, 0x04, 0xF0, 0x22, 0xAE, - 0x07, 0x12, 0x51, 0x73, 0xBF, 0x01, 0x12, 0x90, - 0x81, 0x23, 0xE0, 0x64, 0x02, 0x60, 0x0A, 0xAF, - 0x06, 0x7D, 0x01, 0x12, 0x47, 0x3D, 0x7F, 0x01, - 0x22, 0x7F, 0x00, 0x22, 0x90, 0x01, 0x57, 0xE0, - 0x60, 0x48, 0xE4, 0xF0, 0x90, 0x01, 0x3C, 0x74, - 0x02, 0xF0, 0x90, 0x81, 0x24, 0xE0, 0xFF, 0x13, - 0x13, 0x54, 0x3F, 0x30, 0xE0, 0x0C, 0xEF, 0x54, - 0xFB, 0xF0, 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xFD, - 0xF0, 0x22, 0x90, 0x81, 0x30, 0xE0, 0x04, 0xF0, - 0x90, 0x81, 0x2B, 0xE0, 0x54, 0xEF, 0xF0, 0x90, - 0x81, 0x38, 0xE0, 0xFF, 0x90, 0x81, 0x30, 0xE0, - 0xD3, 0x9F, 0x40, 0x0E, 0x90, 0x80, 0xDE, 0xE0, - 0xB4, 0x01, 0x07, 0x90, 0x81, 0x25, 0xE0, 0x54, - 0xFB, 0xF0, 0x22, 0x90, 0x80, 0x3F, 0xE0, 0xFF, - 0x7D, 0x01, 0x12, 0x6D, 0x69, 0x8E, 0x54, 0x8F, - 0x55, 0xAD, 0x55, 0xAC, 0x54, 0xAF, 0x53, 0x12, - 0x4F, 0x82, 0xAF, 0x55, 0xAE, 0x54, 0x90, 0x04, - 0x80, 0xE0, 0x54, 0x0F, 0xFD, 0xAC, 0x07, 0x74, - 0x11, 0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, - 0x83, 0xE0, 0x44, 0x01, 0xF0, 0x74, 0x11, 0x2C, - 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, - 0x54, 0xFB, 0xF0, 0xAC, 0x07, 0x74, 0x16, 0x2C, - 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, - 0x44, 0xFA, 0xF0, 0x74, 0x15, 0x2C, 0xF5, 0x82, - 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x1F, - 0xF0, 0xAC, 0x07, 0x74, 0x06, 0x2C, 0xF5, 0x82, - 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xE0, 0x44, 0x0F, - 0xF0, 0x90, 0x04, 0x53, 0xE4, 0xF0, 0x90, 0x04, - 0x52, 0xF0, 0x90, 0x04, 0x51, 0x74, 0xFF, 0xF0, - 0x90, 0x04, 0x50, 0x74, 0xFD, 0xF0, 0x74, 0x14, - 0x2C, 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, - 0xE0, 0x54, 0xC0, 0x4D, 0xFD, 0x74, 0x14, 0x2F, - 0xF5, 0x82, 0xE4, 0x34, 0xFC, 0xF5, 0x83, 0xED, - 0xF0, 0x22, 0xAB, 0x07, 0xAA, 0x06, 0xED, 0x2B, - 0xFB, 0xE4, 0x3A, 0xFA, 0xC3, 0x90, 0x80, 0xDB, - 0xE0, 0x9B, 0x90, 0x80, 0xDA, 0xE0, 0x9A, 0x50, - 0x13, 0xA3, 0xE0, 0x24, 0x01, 0xFF, 0x90, 0x80, - 0xDA, 0xE0, 0x34, 0x00, 0xFE, 0xC3, 0xEB, 0x9F, - 0xFB, 0xEA, 0x9E, 0xFA, 0xEA, 0x90, 0xFD, 0x11, - 0xF0, 0xAF, 0x03, 0x74, 0x00, 0x2F, 0xF5, 0x82, - 0xE4, 0x34, 0xFB, 0xF5, 0x83, 0xE0, 0xFF, 0x22, - 0x12, 0x1F, 0xA4, 0xFF, 0x54, 0x01, 0xFE, 0x90, - 0x81, 0x42, 0xE0, 0x54, 0xFE, 0x4E, 0xF0, 0xEF, - 0xC3, 0x13, 0x30, 0xE0, 0x0A, 0x90, 0x00, 0x01, - 0x12, 0x1F, 0xBD, 0x90, 0x81, 0x43, 0xF0, 0x22, - 0x90, 0x81, 0x45, 0xE0, 0x30, 0xE0, 0x2D, 0x90, - 0x81, 0x48, 0xE0, 0x04, 0xF0, 0xE0, 0xFF, 0x90, - 0x81, 0x46, 0xE0, 0xB5, 0x07, 0x1E, 0x90, 0x06, - 0x92, 0xE0, 0x54, 0x1C, 0x70, 0x0B, 0x12, 0x4F, - 0x0B, 0x90, 0x81, 0x49, 0xE0, 0x04, 0xF0, 0x80, - 0x06, 0x90, 0x06, 0x92, 0x74, 0x1C, 0xF0, 0xE4, - 0x90, 0x81, 0x48, 0xF0, 0x22, 0x00, 0xBB, 0x8E, -}; diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c index 51f03c3b53a4..52b3fba0fae1 100644 --- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c +++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c @@ -19,6 +19,7 @@ ******************************************************************************/ #define _HAL_INIT_C_ +#include <linux/firmware.h> #include <drv_types.h> #include <rtw_efuse.h> @@ -588,13 +589,15 @@ s32 rtl8188e_FirmwareDownload(struct adapter *padapter) u8 writeFW_retry = 0; u32 fwdl_start_time; struct hal_data_8188e *pHalData = GET_HAL_DATA(padapter); - - u8 *FwImage; - u32 FwImageLen; + struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); + struct device *device = dvobj_to_dev(dvobj); struct rt_firmware *pFirmware = NULL; + const struct firmware *fw; struct rt_firmware_hdr *pFwHdr = NULL; u8 *pFirmwareBuf; - u32 FirmwareLen; + u32 FirmwareLen; + char fw_name[] = "rtlwifi/rtl8188eufw.bin"; + static int log_version; RT_TRACE(_module_hal_init_c_, _drv_info_, ("+%s\n", __func__)); pFirmware = (struct rt_firmware *)rtw_zmalloc(sizeof(struct rt_firmware)); @@ -603,27 +606,32 @@ s32 rtl8188e_FirmwareDownload(struct adapter *padapter) goto Exit; } - FwImage = (u8 *)Rtl8188E_FwImageArray; - FwImageLen = Rtl8188E_FWImgArrayLength; - - pFirmware->eFWSource = FW_SOURCE_HEADER_FILE; - - switch (pFirmware->eFWSource) { - case FW_SOURCE_IMG_FILE: - break; - case FW_SOURCE_HEADER_FILE: - if (FwImageLen > FW_8188E_SIZE) { - rtStatus = _FAIL; - RT_TRACE(_module_hal_init_c_, _drv_err_, ("Firmware size exceed 0x%X. Check it.\n", FW_8188E_SIZE)); - goto Exit; - } + if (request_firmware(&fw, fw_name, device)) { + rtStatus = _FAIL; + goto Exit; + } + if (!fw) { + pr_err("Firmware %s not available\n", fw_name); + rtStatus = _FAIL; + goto Exit; + } + if (fw->size > FW_8188E_SIZE) { + rtStatus = _FAIL; + RT_TRACE(_module_hal_init_c_, _drv_err_, ("Firmware size exceed 0x%X. Check it.\n", FW_8188E_SIZE)); + goto Exit; + } - pFirmware->szFwBuffer = FwImage; - pFirmware->ulFwLength = FwImageLen; - break; + pFirmware->szFwBuffer = kzalloc(FW_8188E_SIZE, GFP_KERNEL); + if (!pFirmware->szFwBuffer) { + rtStatus = _FAIL; + goto Exit; } + memcpy(pFirmware->szFwBuffer, fw->data, fw->size); + pFirmware->ulFwLength = fw->size; pFirmwareBuf = pFirmware->szFwBuffer; FirmwareLen = pFirmware->ulFwLength; + release_firmware(fw); + DBG_88E_LEVEL(_drv_info_, "+%s: !bUsedWoWLANFw, FmrmwareLen:%d+\n", __func__, FirmwareLen); /* To Check Fw header. Added by tynli. 2009.12.04. */ @@ -633,8 +641,10 @@ s32 rtl8188e_FirmwareDownload(struct adapter *padapter) pHalData->FirmwareSubVersion = pFwHdr->Subversion; pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->Signature); - DBG_88E("%s: fw_ver =%d fw_subver =%d sig = 0x%x\n", - __func__, pHalData->FirmwareVersion, pHalData->FirmwareSubVersion, pHalData->FirmwareSignature); + if (!log_version++) + pr_info("%sFirmware Version %d, SubVersion %d, Signature 0x%x\n", + DRIVER_PREFIX, pHalData->FirmwareVersion, + pHalData->FirmwareSubVersion, pHalData->FirmwareSignature); if (IS_FW_HEADER_EXIST(pFwHdr)) { /* Shift 32 bytes for FW header */ @@ -677,7 +687,7 @@ s32 rtl8188e_FirmwareDownload(struct adapter *padapter) goto Exit; } RT_TRACE(_module_hal_init_c_, _drv_info_, ("Firmware is ready to run!\n")); - + kfree(pFirmware->szFwBuffer); Exit: kfree(pFirmware); diff --git a/drivers/staging/rtl8188eu/hal/usb_ops_linux.c b/drivers/staging/rtl8188eu/hal/usb_ops_linux.c index 2a20f2348108..787763ef74c6 100644 --- a/drivers/staging/rtl8188eu/hal/usb_ops_linux.c +++ b/drivers/staging/rtl8188eu/hal/usb_ops_linux.c @@ -547,6 +547,8 @@ static void usb_read_port_complete(struct urb *purb, struct pt_regs *regs) RT_TRACE(_module_hci_ops_os_c_, _drv_err_, ("usb_read_port_complete : purb->status(%d) != 0\n", purb->status)); DBG_88E("###=> usb_read_port_complete => urb status(%d)\n", purb->status); + skb_put(precvbuf->pskb, purb->actual_length); + precvbuf->pskb = NULL; if (rtw_inc_and_chk_continual_urb_error(adapter_to_dvobj(adapt))) adapt->bSurpriseRemoved = true; diff --git a/drivers/staging/rtl8188eu/include/Hal8188EFWImg_CE.h b/drivers/staging/rtl8188eu/include/Hal8188EFWImg_CE.h deleted file mode 100644 index 949c33b9ed68..000000000000 --- a/drivers/staging/rtl8188eu/include/Hal8188EFWImg_CE.h +++ /dev/null @@ -1,28 +0,0 @@ -/****************************************************************************** -* -* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. -* -* This program is free software; you can redistribute it and/or modify it -* under the terms of version 2 of the GNU General Public License 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 Street, Fifth Floor, Boston, MA 02110, USA -* -* -******************************************************************************/ -#ifndef __INC_HAL8188E_FW_IMG_H -#define __INC_HAL8188E_FW_IMG_H - -/* V10(1641) */ -#define Rtl8188EFWImgArrayLength 13904 - -extern const u8 Rtl8188EFwImgArray[Rtl8188EFWImgArrayLength]; - -#endif /* __INC_HAL8188E_FW_IMG_H */ diff --git a/drivers/staging/rtl8188eu/include/odm_precomp.h b/drivers/staging/rtl8188eu/include/odm_precomp.h index 520cbbaac35f..d1d95f4b87a8 100644 --- a/drivers/staging/rtl8188eu/include/odm_precomp.h +++ b/drivers/staging/rtl8188eu/include/odm_precomp.h @@ -31,11 +31,6 @@ #include <drv_types.h> #include <hal_intf.h> -/* 2 Hardware Parameter Files */ - -#include "Hal8188EFWImg_CE.h" - - /* 2 OutSrc Header Files */ #include "odm.h" diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c index f7b14f8b7b83..1260f10944ef 100644 --- a/drivers/staging/rtl8192e/dot11d.c +++ b/drivers/staging/rtl8192e/dot11d.c @@ -151,7 +151,7 @@ void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr, MaxChnlNum = pTriple->FirstChnl + j; } - pTriple = (struct chnl_txpow_triple *)((u8*)pTriple + 3); + pTriple = (struct chnl_txpow_triple *)((u8 *)pTriple + 3); } UPDATE_CIE_SRC(dev, pTaddr); diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 7d322f3980e1..b01f6f5c2c44 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c @@ -1888,9 +1888,8 @@ void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); skb_push(skb, priv->rtllib->tx_headroom); ret = rtl8192_tx(dev, skb); - if (ret != 0) { + if (ret != 0) kfree_skb(skb); - }; if (queue_index != MGNT_QUEUE) { priv->rtllib->stats.tx_bytes += (skb->len - @@ -1898,7 +1897,6 @@ void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, priv->rtllib->stats.tx_packets++; } - return; } @@ -1930,15 +1928,11 @@ int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) tcb_desc->bTxEnableFwCalcDur = 1; skb_push(skb, priv->rtllib->tx_headroom); ret = rtl8192_tx(dev, skb); - if (ret != 0) { + if (ret != 0) kfree_skb(skb); - }; } - - return ret; - } static void rtl8192_tx_isr(struct net_device *dev, int prio) diff --git a/drivers/staging/rtl8192u/dot11d.h b/drivers/staging/rtl8192u/dot11d.h deleted file mode 100644 index 92e7a00f3ee1..000000000000 --- a/drivers/staging/rtl8192u/dot11d.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef __INC_DOT11D_H -#define __INC_DOT11D_H - -#include "ieee80211/ieee80211.h" - - -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 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/rtl8192u/ieee80211/dot11d.h b/drivers/staging/rtl8192u/ieee80211/dot11d.h index 6aa8c15eba39..bd75e29adc2c 100644 --- a/drivers/staging/rtl8192u/ieee80211/dot11d.h +++ b/drivers/staging/rtl8192u/ieee80211/dot11d.h @@ -4,42 +4,43 @@ #include "ieee80211.h" -//#define DOT11D_MAX_CHNL_NUM 83 - typedef struct _CHNL_TXPOWER_TRIPLE { u8 FirstChnl; u8 NumChnls; u8 MaxTxPowerInDbm; -}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; +} CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; typedef enum _DOT11D_STATE { DOT11D_STATE_NONE = 0, DOT11D_STATE_LEARNED, DOT11D_STATE_DONE, -}DOT11D_STATE; +} DOT11D_STATE; typedef struct _RT_DOT11D_INFO { - //DECLARE_RT_OBJECT(RT_DOT11D_INFO); + /* DECLARE_RT_OBJECT(RT_DOT11D_INFO); */ - bool bEnabled; // dot11MultiDomainCapabilityEnabled + bool bEnabled; /* dot11MultiDomainCapabilityEnabled */ - u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element. + 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 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 channel_map[MAX_CHANNEL_NUMBER+1]; /* !Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) */ 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]) +} 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_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) @@ -51,9 +52,9 @@ typedef struct _RT_DOT11D_INFO { (!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 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 UPDATE_CIE_WATCHDOG(__pIeeeDev) (++GET_CIE_WATCHDOG(__pIeeeDev)) #define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) @@ -72,7 +73,7 @@ void Dot11d_UpdateCountryIe( struct ieee80211_device *dev, u8 *pTaddr, - u16 CoutryIeLen, + u16 CoutryIeLen, u8 *pCoutryIe ); @@ -96,4 +97,4 @@ int ToLegalChannel( struct ieee80211_device *dev, u8 channel ); -#endif // #ifndef __INC_DOT11D_H +#endif /* #ifndef __INC_DOT11D_H */ diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c index 434c43127183..4b036a8db5a1 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c @@ -241,7 +241,7 @@ static int debug = \ //IEEE80211_DL_DATA | IEEE80211_DL_ERR //awayls open this flags to show error out ; -struct proc_dir_entry *ieee80211_proc; +static struct proc_dir_entry *ieee80211_proc; static int show_debug_level(struct seq_file *m, void *v) { diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c index 59900bfa1c18..e730ed64c0fe 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c @@ -2166,7 +2166,8 @@ static inline u8 ieee80211_SignalStrengthTranslate( return RetSS; } -long ieee80211_translate_todbm(u8 signal_strength_index )// 0-100 index. +/* 0-100 index */ +static long ieee80211_translate_todbm(u8 signal_strength_index) { long signal_power; // in dBm. diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c index a7bcc64ff226..682659a749b6 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c @@ -238,7 +238,7 @@ void ieee80211_txb_free(struct ieee80211_txb *txb) { } struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, - int gfp_mask) + gfp_t gfp_mask) { struct ieee80211_txb *txb; int i; @@ -303,7 +303,8 @@ ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network) } #define SN_LESS(a, b) (((a-b)&0x800)!=0) -void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, struct sk_buff *skb, cb_desc *tcb_desc) +static void ieee80211_tx_query_agg_cap(struct ieee80211_device *ieee, + struct sk_buff *skb, cb_desc *tcb_desc) { PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; PTX_TS_RECORD pTxTs = NULL; @@ -412,7 +413,8 @@ ieee80211_query_HTCapShortGI(struct ieee80211_device *ieee, cb_desc *tcb_desc) tcb_desc->bUseShortGI = true; } -void ieee80211_query_BandwidthMode(struct ieee80211_device *ieee, cb_desc *tcb_desc) +static void ieee80211_query_BandwidthMode(struct ieee80211_device *ieee, + cb_desc *tcb_desc) { PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; @@ -432,7 +434,9 @@ void ieee80211_query_BandwidthMode(struct ieee80211_device *ieee, cb_desc *tcb_d return; } -void ieee80211_query_protectionmode(struct ieee80211_device *ieee, cb_desc *tcb_desc, struct sk_buff *skb) +static void ieee80211_query_protectionmode(struct ieee80211_device *ieee, + cb_desc *tcb_desc, + struct sk_buff *skb) { // Common Settings tcb_desc->bRTSSTBC = false; @@ -543,7 +547,8 @@ NO_PROTECTION: } -void ieee80211_txrate_selectmode(struct ieee80211_device *ieee, cb_desc *tcb_desc) +static void ieee80211_txrate_selectmode(struct ieee80211_device *ieee, + cb_desc *tcb_desc) { #ifdef TO_DO_LIST if(!IsDataFrame(pFrame)) @@ -573,7 +578,8 @@ void ieee80211_txrate_selectmode(struct ieee80211_device *ieee, cb_desc *tcb_des } } -void ieee80211_query_seqnum(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *dst) +static void ieee80211_query_seqnum(struct ieee80211_device *ieee, + struct sk_buff *skb, u8 *dst) { if (is_multicast_ether_addr(dst)) return; diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index db0db9347487..3684da340bd4 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -251,7 +251,8 @@ static struct sk_buff *ieee80211_DELBA( * output: none * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does ********************************************************************************************************************/ -void ieee80211_send_ADDBAReq(struct ieee80211_device *ieee, u8 *dst, PBA_RECORD pBA) +static void ieee80211_send_ADDBAReq(struct ieee80211_device *ieee, + u8 *dst, PBA_RECORD pBA) { struct sk_buff *skb = NULL; skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero. @@ -278,7 +279,8 @@ void ieee80211_send_ADDBAReq(struct ieee80211_device *ieee, u8 *dst, PBA_RECORD * output: none * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does ********************************************************************************************************************/ -void ieee80211_send_ADDBARsp(struct ieee80211_device *ieee, u8 *dst, PBA_RECORD pBA, u16 StatusCode) +static void ieee80211_send_ADDBARsp(struct ieee80211_device *ieee, u8 *dst, + PBA_RECORD pBA, u16 StatusCode) { struct sk_buff *skb = NULL; skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames diff --git a/drivers/staging/rtl8192u/ieee80211_crypt.h b/drivers/staging/rtl8192u/ieee80211_crypt.h deleted file mode 100644 index 0b4ea431982d..000000000000 --- a/drivers/staging/rtl8192u/ieee80211_crypt.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Original code based on Host AP (software wireless LAN access point) driver - * for Intersil Prism2/2.5/3. - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * <[email protected]> - * Copyright (c) 2002-2003, Jouni Malinen <[email protected]> - * - * Adaption to a generic IEEE 802.11 stack by James Ketrenos - * <[email protected]> - * - * Copyright (c) 2004, Intel Corporation - * - * 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. See README and COPYING for - * more details. - */ - -/* - * This file defines the interface to the ieee80211 crypto module. - */ -#ifndef IEEE80211_CRYPT_H -#define IEEE80211_CRYPT_H - -#include <linux/skbuff.h> - -struct ieee80211_crypto_ops { - const char *name; - - /* init new crypto context (e.g., allocate private data space, - * select IV, etc.); returns NULL on failure or pointer to allocated - * private data on success */ - void * (*init)(int keyidx); - - /* deinitialize crypto context and free allocated private data */ - void (*deinit)(void *priv); - - /* encrypt/decrypt return < 0 on error or >= 0 on success. The return - * value from decrypt_mpdu is passed as the keyidx value for - * decrypt_msdu. skb must have enough head and tail room for the - * encryption; if not, error will be returned; these functions are - * called for all MPDUs (i.e., fragments). - */ - int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); - int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); - - /* These functions are called for full MSDUs, i.e. full frames. - * These can be NULL if full MSDU operations are not needed. */ - int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv); - int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len, - void *priv); - - int (*set_key)(void *key, int len, u8 *seq, void *priv); - int (*get_key)(void *key, int len, u8 *seq, void *priv); - - /* procfs handler for printing out key information and possible - * statistics */ - char * (*print_stats)(char *p, void *priv); - - /* maximum number of bytes added by encryption; encrypt buf is - * allocated with extra_prefix_len bytes, copy of in_buf, and - * extra_postfix_len; encrypt need not use all this space, but - * the result must start at the beginning of the buffer and correct - * length must be returned */ - int extra_prefix_len, extra_postfix_len; - - struct module *owner; -}; - -struct ieee80211_crypt_data { - struct list_head list; /* delayed deletion list */ - struct ieee80211_crypto_ops *ops; - void *priv; - atomic_t refcnt; -}; - -int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops); -int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops); -struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name); -void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int); -void ieee80211_crypt_deinit_handler(unsigned long); -void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, - struct ieee80211_crypt_data **crypt); - -#endif diff --git a/drivers/staging/rtl8192u/r8180_pm.c b/drivers/staging/rtl8192u/r8180_pm.c deleted file mode 100644 index 999968d41720..000000000000 --- a/drivers/staging/rtl8192u/r8180_pm.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - Power management interface routines. - Written by Mariusz Matuszek. - This code is currently just a placeholder for later work and - does not do anything useful. - - This is part of rtl8180 OpenSource driver. - Copyright (C) Andrea Merello 2004 <[email protected]> - Released under the terms of GPL (General Public Licence) -*/ - -#ifdef CONFIG_RTL8180_PM - - -#include "r8180_hw.h" -#include "r8180_pm.h" - -int rtl8180_save_state (struct pci_dev *dev, u32 state) -{ - printk(KERN_NOTICE "r8180 save state call (state %u).\n", state); - return(-EAGAIN); -} - - -int rtl8180_suspend (struct pci_dev *dev, u32 state) -{ - printk(KERN_NOTICE "r8180 suspend call (state %u).\n", state); - return(-EAGAIN); -} - - -int rtl8180_resume (struct pci_dev *dev) -{ - printk(KERN_NOTICE "r8180 resume call.\n"); - return(-EAGAIN); -} - - -int rtl8180_enable_wake (struct pci_dev *dev, u32 state, int enable) -{ - printk(KERN_NOTICE "r8180 enable wake call (state %u, enable %d).\n", - state, enable); - return(-EAGAIN); -} - - - -#endif //CONFIG_RTL8180_PM diff --git a/drivers/staging/rtl8192u/r8180_pm.h b/drivers/staging/rtl8192u/r8180_pm.h deleted file mode 100644 index 4be63da0b781..000000000000 --- a/drivers/staging/rtl8192u/r8180_pm.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Power management interface routines. - Written by Mariusz Matuszek. - This code is currently just a placeholder for later work and - does not do anything useful. - - This is part of rtl8180 OpenSource driver. - Copyright (C) Andrea Merello 2004 <[email protected]> - Released under the terms of GPL (General Public Licence) - -*/ - -#ifdef CONFIG_RTL8180_PM - -#ifndef R8180_PM_H -#define R8180_PM_H - -#include <linux/types.h> -#include <linux/pci.h> - -int rtl8180_save_state (struct pci_dev *dev, u32 state); -int rtl8180_suspend (struct pci_dev *dev, u32 state); -int rtl8180_resume (struct pci_dev *dev); -int rtl8180_enable_wake (struct pci_dev *dev, u32 state, int enable); - -#endif //R8180_PM_H - -#endif // CONFIG_RTL8180_PM diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h index 4c46bb25a6b3..ad3bc567d35a 100644 --- a/drivers/staging/rtl8192u/r8192U.h +++ b/drivers/staging/rtl8192u/r8192U.h @@ -1154,14 +1154,6 @@ typedef enum { NIC_8192E = 3, } nic_t; - -#ifdef JOHN_HWSEC -struct ssid_thread { - struct net_device *dev; - u8 name[IW_ESSID_MAX_SIZE + 1]; -}; -#endif - bool init_firmware(struct net_device *dev); short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb); short rtl8192_tx(struct net_device *dev, struct sk_buff *skb); diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index cd0946db025c..63a4cdf1dc04 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -392,7 +392,7 @@ int read_nic_word(struct net_device *dev, int indx, u16 *data) return 0; } -int read_nic_word_E(struct net_device *dev, int indx, u16 *data) +static int read_nic_word_E(struct net_device *dev, int indx, u16 *data) { int status; struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); @@ -585,7 +585,7 @@ static int proc_get_stats_rx(struct seq_file *m, void *v) return 0; } -void rtl8192_proc_module_init(void) +static void rtl8192_proc_module_init(void) { RT_TRACE(COMP_INIT, "Initializing proc filesystem"); rtl8192_proc = proc_mkdir(RTL819xU_MODULE_NAME, init_net.proc_net); @@ -631,7 +631,7 @@ static const struct rtl8192_proc_file rtl8192_proc_files[] = { { "" } }; -void rtl8192_proc_init_one(struct net_device *dev) +static void rtl8192_proc_init_one(struct net_device *dev) { const struct rtl8192_proc_file *f; struct proc_dir_entry *dir; @@ -656,7 +656,7 @@ void rtl8192_proc_init_one(struct net_device *dev) } } -void rtl8192_proc_remove_one(struct net_device *dev) +static void rtl8192_proc_remove_one(struct net_device *dev) { remove_proc_subtree(dev->name, rtl8192_proc); } @@ -755,7 +755,7 @@ void rtl8192_set_chan(struct net_device *dev, short ch) static void rtl8192_rx_isr(struct urb *urb); -u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats) +static u32 get_rxpacket_shiftbytes_819xusb(struct ieee80211_rx_stats *pstats) { #ifdef USB_RX_AGGREGATION_SUPPORT @@ -998,8 +998,8 @@ static void rtl8192_rx_isr(struct urb *urb) netdev_err(dev, "can not submit rxurb, err is %x, URB status is %x\n", err, urb->status); } -u32 rtl819xusb_rx_command_packet(struct net_device *dev, - struct ieee80211_rx_stats *pstats) +static u32 rtl819xusb_rx_command_packet(struct net_device *dev, + struct ieee80211_rx_stats *pstats) { u32 status; @@ -1609,13 +1609,6 @@ short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb) #else idx_pipe = 0x04; #endif -#ifdef JOHN_DUMP_TXDESC - int i; - printk("<Tx descriptor>--rate %x---", rate); - for (i = 0; i < 8; i++) - printk("%8x ", tx[i]); - printk("\n"); -#endif usb_fill_bulk_urb(tx_urb, priv->udev, usb_sndbulkpipe(priv->udev, idx_pipe), skb->data, skb->len, rtl8192_tx_isr, skb); @@ -1636,7 +1629,7 @@ short rtl819xU_tx_cmd(struct net_device *dev, struct sk_buff *skb) * * \param QUEUEID Software Queue */ -u8 MapHwQueueToFirmwareQueue(u8 QueueID) +static u8 MapHwQueueToFirmwareQueue(u8 QueueID) { u8 QueueSelect = 0x0; //defualt set to @@ -1723,7 +1716,7 @@ u8 MRateToHwRate8190Pci(u8 rate) } -u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc) +static u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc) { u8 tmp_Short; @@ -1934,7 +1927,7 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff *skb) } } -short rtl8192_usb_initendpoints(struct net_device *dev) +static short rtl8192_usb_initendpoints(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); @@ -1992,7 +1985,7 @@ short rtl8192_usb_initendpoints(struct net_device *dev) } #ifdef THOMAS_BEACON -void rtl8192_usb_deleteendpoints(struct net_device *dev) +static void rtl8192_usb_deleteendpoints(struct net_device *dev) { int i; struct r8192_priv *priv = ieee80211_priv(dev); @@ -2009,7 +2002,7 @@ void rtl8192_usb_deleteendpoints(struct net_device *dev) priv->oldaddr = NULL; if (priv->pp_rxskb) { kfree(priv->pp_rxskb); - priv->pp_rxskb = 0; + priv->pp_rxskb = NULL; } } #else @@ -2292,7 +2285,7 @@ void rtl8192_update_ratr_table(struct net_device *dev) static u8 ccmp_ie[4] = {0x00, 0x50, 0xf2, 0x04}; static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04}; -bool GetNmodeSupportBySecCfg8192(struct net_device *dev) +static bool GetNmodeSupportBySecCfg8192(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); struct ieee80211_device *ieee = priv->ieee80211; @@ -3167,7 +3160,7 @@ static struct net_device_stats *rtl8192_stats(struct net_device *dev) return &priv->ieee80211->stats; } -bool HalTxCheckStuck819xUsb(struct net_device *dev) +static bool HalTxCheckStuck819xUsb(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); u16 RegTxCounter; @@ -3217,7 +3210,7 @@ RESET_TYPE TxCheckStuck(struct net_device *dev) return RESET_TYPE_NORESET; } -bool HalRxCheckStuck819xUsb(struct net_device *dev) +static bool HalRxCheckStuck819xUsb(struct net_device *dev) { u16 RegRxCounter; struct r8192_priv *priv = ieee80211_priv(dev); @@ -3259,7 +3252,7 @@ bool HalRxCheckStuck819xUsb(struct net_device *dev) return bStuck; } -RESET_TYPE RxCheckStuck(struct net_device *dev) +static RESET_TYPE RxCheckStuck(struct net_device *dev) { struct r8192_priv *priv = ieee80211_priv(dev); bool bRxCheck = FALSE; @@ -3859,15 +3852,6 @@ int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) } } } -#ifdef JOHN_HWSEC_DEBUG - //john's test 0711 - printk("@@ wrq->u pointer = "); - for (i = 0; i < wrq->u.data.length; i++) { - if (i%10 == 0) printk("\n"); - printk("%8x|", ((u32 *)wrq->u.data.pointer)[i]); - } - printk("\n"); -#endif /*JOHN_HWSEC_DEBUG*/ ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data); break; @@ -3952,7 +3936,8 @@ u8 HwRateToMRate90(bool bIsHT, u8 rate) * Return: * None */ -void UpdateRxPktTimeStamp8190(struct net_device *dev, struct ieee80211_rx_stats *stats) +static void UpdateRxPktTimeStamp8190(struct net_device *dev, + struct ieee80211_rx_stats *stats) { struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); @@ -4209,7 +4194,7 @@ static u8 rtl819x_evm_dbtopercentage(char value) // We want good-looking for signal strength/quality // 2007/7/19 01:09, by cosa. // -long rtl819x_signal_scale_mapping(long currsig) +static long rtl819x_signal_scale_mapping(long currsig) { long retsig; @@ -4478,9 +4463,9 @@ void rtl8192_record_rxdesc_forlateruse(struct ieee80211_rx_stats *psrc_stats, } -void TranslateRxSignalStuff819xUsb(struct sk_buff *skb, - struct ieee80211_rx_stats *pstats, - rx_drvinfo_819x_usb *pdrvinfo) +static void TranslateRxSignalStuff819xUsb(struct sk_buff *skb, + struct ieee80211_rx_stats *pstats, + rx_drvinfo_819x_usb *pdrvinfo) { // TODO: We must only check packet for current MAC address. Not finish rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb; @@ -4549,8 +4534,9 @@ void TranslateRxSignalStuff819xUsb(struct sk_buff *skb, * Return: * None */ -void UpdateReceivedRateHistogramStatistics8190(struct net_device *dev, - struct ieee80211_rx_stats *stats) +static void +UpdateReceivedRateHistogramStatistics8190(struct net_device *dev, + struct ieee80211_rx_stats *stats) { struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev); u32 rcvType = 1; //0: Total, 1:OK, 2:CRC, 3:ICV @@ -4614,7 +4600,9 @@ void UpdateReceivedRateHistogramStatistics8190(struct net_device *dev, } -void query_rxdesc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats, bool bIsRxAggrSubframe) +static void query_rxdesc_status(struct sk_buff *skb, + struct ieee80211_rx_stats *stats, + bool bIsRxAggrSubframe) { rtl8192_rx_info *info = (struct rtl8192_rx_info *)skb->cb; struct net_device *dev = info->dev; @@ -4930,7 +4918,8 @@ void rtl819xusb_process_received_packet(struct net_device *dev, } -void query_rx_cmdpkt_desc_status(struct sk_buff *skb, struct ieee80211_rx_stats *stats) +static void query_rx_cmdpkt_desc_status(struct sk_buff *skb, + struct ieee80211_rx_stats *stats) { rx_desc_819x_usb *desc = (rx_desc_819x_usb *)skb->data; diff --git a/drivers/staging/rtl8192u/r8192U_wx.c b/drivers/staging/rtl8192u/r8192U_wx.c index 61f6620213e2..c70af014a316 100644 --- a/drivers/staging/rtl8192u/r8192U_wx.c +++ b/drivers/staging/rtl8192u/r8192U_wx.c @@ -127,156 +127,6 @@ static int r8192_wx_get_power(struct net_device *dev, return ieee80211_wx_get_power(priv->ieee80211,info,wrqu,extra); } -#ifdef JOHN_IOCTL -u16 read_rtl8225(struct net_device *dev, u8 addr); -void write_rtl8225(struct net_device *dev, u8 adr, u16 data); -u32 john_read_rtl8225(struct net_device *dev, u8 adr); -void _write_rtl8225(struct net_device *dev, u8 adr, u16 data); - -static int r8192_wx_read_regs(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = ieee80211_priv(dev); - u8 addr; - u16 data1; - - down(&priv->wx_sem); - - - get_user(addr,(u8 *)wrqu->data.pointer); - data1 = read_rtl8225(dev, addr); - wrqu->data.length = data1; - - up(&priv->wx_sem); - return 0; - -} - -static int r8192_wx_write_regs(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = ieee80211_priv(dev); - u8 addr; - - down(&priv->wx_sem); - - get_user(addr, (u8 *)wrqu->data.pointer); - write_rtl8225(dev, addr, wrqu->data.length); - - up(&priv->wx_sem); - return 0; - -} - -void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data); -u8 rtl8187_read_phy(struct net_device *dev,u8 adr, u32 data); - -static int r8192_wx_read_bb(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = ieee80211_priv(dev); - u8 databb; - - down(&priv->wx_sem); - - databb = rtl8187_read_phy(dev, (u8)wrqu->data.length, 0x00000000); - wrqu->data.length = databb; - - up(&priv->wx_sem); - return 0; -} - -void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data); -static int r8192_wx_write_bb(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = ieee80211_priv(dev); - u8 databb; - - down(&priv->wx_sem); - - get_user(databb, (u8 *)wrqu->data.pointer); - rtl8187_write_phy(dev, wrqu->data.length, databb); - - up(&priv->wx_sem); - return 0; - -} - - -static int r8192_wx_write_nicb(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = ieee80211_priv(dev); - u32 addr; - - down(&priv->wx_sem); - - get_user(addr, (u32 *)wrqu->data.pointer); - write_nic_byte(dev, addr, wrqu->data.length); - - up(&priv->wx_sem); - return 0; - -} -static int r8192_wx_read_nicb(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = ieee80211_priv(dev); - u32 addr; - u16 data1; - - down(&priv->wx_sem); - - get_user(addr,(u32 *)wrqu->data.pointer); - read_nic_byte(dev, addr, &data1); - wrqu->data.length = data1; - - up(&priv->wx_sem); - return 0; -} - -static int r8192_wx_get_ap_status(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8192_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - struct ieee80211_network *target; - int name_len; - - down(&priv->wx_sem); - - //count the length of input ssid - for(name_len=0 ; ((char *)wrqu->data.pointer)[name_len]!='\0' ; name_len++); - - //search for the corresponding info which is received - list_for_each_entry(target, &ieee->network_list, list) { - if ( (target->ssid_len == name_len) && - (strncmp(target->ssid, (char *)wrqu->data.pointer, name_len)==0)){ - if(target->wpa_ie_len>0 || target->rsn_ie_len>0 ) - //set flags=1 to indicate this ap is WPA - wrqu->data.flags = 1; - else wrqu->data.flags = 0; - - - break; - } - } - - up(&priv->wx_sem); - return 0; -} - - - -#endif static int r8192_wx_force_reset(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -1106,46 +956,7 @@ static const struct iw_priv_args r8192_private_args[] = { { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" - } -#ifdef JOHN_IOCTL - , - { - SIOCIWFIRSTPRIV + 0x3, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readRF" - } - , - { - SIOCIWFIRSTPRIV + 0x4, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeRF" - } - , - { - SIOCIWFIRSTPRIV + 0x5, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readBB" - } - , - { - SIOCIWFIRSTPRIV + 0x6, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeBB" - } - , - { - SIOCIWFIRSTPRIV + 0x7, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readnicb" - } - , - { - SIOCIWFIRSTPRIV + 0x8, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writenicb" - } - , - { - SIOCIWFIRSTPRIV + 0x9, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo" - } - -#endif - , + }, { SIOCIWFIRSTPRIV + 0x3, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset" @@ -1163,15 +974,6 @@ static iw_handler r8192_private_handler[] = { // r8192_wx_set_monitor_type, r8192_wx_set_scan_type, r8192_wx_set_rawtx, -#ifdef JOHN_IOCTL - r8192_wx_read_regs, - r8192_wx_write_regs, - r8192_wx_read_bb, - r8192_wx_write_bb, - r8192_wx_read_nicb, - r8192_wx_write_nicb, - r8192_wx_get_ap_status, -#endif //r8192_wx_null, r8192_wx_force_reset, }; diff --git a/drivers/staging/rtl8192u/r819xU_HTType.h b/drivers/staging/rtl8192u/r819xU_HTType.h index 19a7bdd1973a..2cbb8e6584f8 100644 --- a/drivers/staging/rtl8192u/r819xU_HTType.h +++ b/drivers/staging/rtl8192u/r819xU_HTType.h @@ -2,41 +2,36 @@ #define _R819XU_HTTYPE_H_ -//------------------------------------------------------------ -// The HT Capability element is present in beacons, association request, -// reassociation request and probe response frames -//------------------------------------------------------------ - -// -// Operation mode value -// +/*---------------------------------------------------------------------- + * The HT Capability element is present in beacons, association request, + * reassociation request and probe response frames + *----------------------------------------------------------------------*/ + +/* Operation mode value */ #define HT_OPMODE_NO_PROTECT 0 #define HT_OPMODE_OPTIONAL 1 -#define HT_OPMODE_40MHZ_PROTECT 2 +#define HT_OPMODE_40MHZ_PROTECT 2 #define HT_OPMODE_MIXED 3 -// -// MIMO Power Save Settings -// -#define MIMO_PS_STATIC 0 +/* MIMO Power Save Settings */ +#define MIMO_PS_STATIC 0 #define MIMO_PS_DYNAMIC 1 #define MIMO_PS_NOLIMIT 3 -// -// There should be 128 bits to cover all of the MCS rates. However, since -// 8190 does not support too much rates, one integer is quite enough. -// +/* There should be 128 bits to cover all of the MCS rates. However, since + * 8190 does not support too much rates, one integer is quite enough. */ -#define sHTCLng 4 +#define sHTCLng 4 -#define HT_SUPPORTED_MCS_1SS_BITMAP 0x000000ff -#define HT_SUPPORTED_MCS_2SS_BITMAP 0x0000ff00 -#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP HT_MCS_1SS_BITMAP|HT_MCS_1SS_2SS_BITMAP +#define HT_SUPPORTED_MCS_1SS_BITMAP 0x000000ff +#define HT_SUPPORTED_MCS_2SS_BITMAP 0x0000ff00 +#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP \ + (HT_MCS_1SS_BITMAP | HT_MCS_1SS_2SS_BITMAP) -typedef enum _HT_MCS_RATE{ +typedef enum _HT_MCS_RATE { HT_MCS0 = 0x00000001, HT_MCS1 = 0x00000002, HT_MCS2 = 0x00000004, @@ -47,71 +42,67 @@ typedef enum _HT_MCS_RATE{ HT_MCS7 = 0x00000080, HT_MCS8 = 0x00000100, HT_MCS9 = 0x00000200, - HT_MCS10 = 0x00000400, - HT_MCS11 = 0x00000800, - HT_MCS12 = 0x00001000, - HT_MCS13 = 0x00002000, - HT_MCS14 = 0x00004000, - HT_MCS15 = 0x00008000, - // Do not define MCS32 here although 8190 support MCS32 -}HT_MCS_RATE,*PHT_MCS_RATE; - -// -// Represent Channel Width in HT Capabilities -// -typedef enum _HT_CHANNEL_WIDTH{ - HT_CHANNEL_WIDTH_20 = 0, + HT_MCS10 = 0x00000400, + HT_MCS11 = 0x00000800, + HT_MCS12 = 0x00001000, + HT_MCS13 = 0x00002000, + HT_MCS14 = 0x00004000, + HT_MCS15 = 0x00008000, + /* Do not define MCS32 here although 8190 support MCS32 */ +} HT_MCS_RATE, *PHT_MCS_RATE; + +/* Represent Channel Width in HT Capabilities */ +typedef enum _HT_CHANNEL_WIDTH { + HT_CHANNEL_WIDTH_20 = 0, HT_CHANNEL_WIDTH_20_40 = 1, -}HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH; +} HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH; -// -// Represent Extension Channel Offset in HT Capabilities -// This is available only in 40Mhz mode. -// -typedef enum _HT_EXTCHNL_OFFSET{ +/* Represent Extension Channel Offset in HT Capabilities + * This is available only in 40Mhz mode. */ +typedef enum _HT_EXTCHNL_OFFSET { HT_EXTCHNL_OFFSET_NO_EXT = 0, - HT_EXTCHNL_OFFSET_UPPER = 1, + HT_EXTCHNL_OFFSET_UPPER = 1, HT_EXTCHNL_OFFSET_NO_DEF = 2, - HT_EXTCHNL_OFFSET_LOWER = 3, -}HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET; - -typedef enum _CHNLOP{ - CHNLOP_NONE = 0, // No Action now - CHNLOP_SCAN = 1, // Scan in progress - CHNLOP_SWBW = 2, // Bandwidth switching in progress - CHNLOP_SWCHNL = 3, // Software Channel switching in progress + HT_EXTCHNL_OFFSET_LOWER = 3, +} HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET; + +typedef enum _CHNLOP { + CHNLOP_NONE = 0, /* No Action now */ + CHNLOP_SCAN = 1, /* Scan in progress */ + CHNLOP_SWBW = 2, /* Bandwidth switching in progress */ + CHNLOP_SWCHNL = 3, /* Software Channel switching in progress */ } CHNLOP, *PCHNLOP; -// Determine if the Channel Operation is in progress +/* Determine if the Channel Operation is in progress */ #define CHHLOP_IN_PROGRESS(_pHTInfo) \ - ((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? TRUE : FALSE + (((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? TRUE : FALSE) -typedef enum _HT_ACTION{ +typedef enum _HT_ACTION { ACT_RECOMMAND_WIDTH = 0, ACT_MIMO_PWR_SAVE = 1, - ACT_PSMP = 2, + ACT_PSMP = 2, ACT_SET_PCO_PHASE = 3, - ACT_MIMO_CHL_MEASURE = 4, - ACT_RECIPROCITY_CORRECT = 5, + ACT_MIMO_CHL_MEASURE = 4, + ACT_RECIPROCITY_CORRECT = 5, ACT_MIMO_CSI_MATRICS = 6, - ACT_MIMO_NOCOMPR_STEER = 7, + ACT_MIMO_NOCOMPR_STEER = 7, ACT_MIMO_COMPR_STEER = 8, ACT_ANTENNA_SELECT = 9, } HT_ACTION, *PHT_ACTION; -/* 2007/06/07 MH Define sub-carrier mode for 40MHZ. */ -typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier{ +/* Define sub-carrier mode for 40MHZ. */ +typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier { SC_MODE_DUPLICATE = 0, - SC_MODE_LOWER = 1, - SC_MODE_UPPER = 2, + SC_MODE_LOWER = 1, + SC_MODE_UPPER = 2, SC_MODE_FULL40MHZ = 3, -}HT_BW40_SC_E; +} HT_BW40_SC_E; -typedef struct _HT_CAPABILITY_ELE{ +typedef struct _HT_CAPABILITY_ELE { - //HT capability info + /* HT capability info */ u8 AdvCoding:1; u8 ChlWidth:1; u8 MimoPwrSave:2; @@ -127,32 +118,32 @@ typedef struct _HT_CAPABILITY_ELE{ u8 Rsvd1:1; u8 LSigTxopProtect:1; - //MAC HT parameters info + /* MAC HT parameters info */ u8 MaxRxAMPDUFactor:2; u8 MPDUDensity:3; u8 Rsvd2:3; - //Supported MCS set + /* Supported MCS set */ u8 MCS[16]; - //Extended HT Capability Info + /* Extended HT Capability Info */ u16 ExtHTCapInfo; - //TXBF Capabilities + /* TXBF Capabilities */ u8 TxBFCap[4]; - //Antenna Selection Capabilities + /* Antenna Selection Capabilities */ u8 ASCap; -}__attribute__((packed)) HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE; +} __packed HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE; -//------------------------------------------------------------ -// The HT Information element is present in beacons -// Only AP is required to include this element -//------------------------------------------------------------ +/*------------------------------------------------------------ + * The HT Information element is present in beacons + * Only AP is required to include this element + *------------------------------------------------------------*/ -typedef struct _HT_INFORMATION_ELE{ +typedef struct _HT_INFORMATION_ELE { u8 ControlChl; u8 ExtChlOffset:2; @@ -177,146 +168,146 @@ typedef struct _HT_INFORMATION_ELE{ u8 Rsvd4:4; u8 BasicMSC[16]; -}__attribute__((packed)) HT_INFORMATION_ELE, *PHT_INFORMATION_ELE; +} __packed HT_INFORMATION_ELE, *PHT_INFORMATION_ELE; -// -// MIMO Power Save control field. -// This is appear in MIMO Power Save Action Frame -// -typedef struct _MIMOPS_CTRL{ +/* MIMO Power Save control field. + * This is appear in MIMO Power Save Action Frame */ +typedef struct _MIMOPS_CTRL { u8 MimoPsEnable:1; u8 MimoPsMode:1; u8 Reserved:6; } MIMOPS_CTRL, *PMIMOPS_CTRL; -typedef enum _HT_SPEC_VER{ +typedef enum _HT_SPEC_VER { HT_SPEC_VER_IEEE = 0, HT_SPEC_VER_EWC = 1, -}HT_SPEC_VER, *PHT_SPEC_VER; +} HT_SPEC_VER, *PHT_SPEC_VER; -typedef enum _HT_AGGRE_MODE_E{ +typedef enum _HT_AGGRE_MODE_E { HT_AGG_AUTO = 0, HT_AGG_FORCE_ENABLE = 1, HT_AGG_FORCE_DISABLE = 2, -}HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E; - -//------------------------------------------------------------ -// The Data structure is used to keep HT related variables when card is -// configured as non-AP STA mode. **Note** Current_xxx should be set -// to default value in HTInitializeHTInfo() -//------------------------------------------------------------ - -typedef struct _RT_HIGH_THROUGHPUT{ -// DECLARE_RT_OBJECT(_RT_HIGH_THROUGHPUT); - u8 bEnableHT; - u8 bCurrentHTSupport; - - u8 bRegBW40MHz; // Tx 40MHz channel capability - u8 bCurBW40MHz; // Tx 40MHz channel capability - - u8 bRegShortGI40MHz; // Tx Short GI for 40Mhz - u8 bCurShortGI40MHz; // Tx Short GI for 40MHz - - u8 bRegShortGI20MHz; // Tx Short GI for 20MHz - u8 bCurShortGI20MHz; // Tx Short GI for 20MHz - - u8 bRegSuppCCK; // Tx CCK rate capability - u8 bCurSuppCCK; // Tx CCK rate capability - - // 802.11n spec version for "peer" - HT_SPEC_VER ePeerHTSpecVer; - +} HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E; - // HT related information for "Self" - HT_CAPABILITY_ELE SelfHTCap; // This is HT cap element sent to peer STA, which also indicate HT Rx capabilities. - HT_INFORMATION_ELE SelfHTInfo; // This is HT info element sent to peer STA, which also indicate HT Rx capabilities. +/*---------------------------------------------------------------------------- + * The Data structure is used to keep HT related variables when card is + * configured as non-AP STA mode. + * **Note** Current_xxx should be set to default value in HTInitializeHTInfo() + *----------------------------------------------------------------------------*/ - // HT related information for "Peer" - u8 PeerHTCapBuf[32]; - u8 PeerHTInfoBuf[32]; - - - // A-MSDU related - u8 bAMSDU_Support; // This indicates Tx A-MSDU capability - u16 nAMSDU_MaxSize; // This indicates Tx A-MSDU capability - u8 bCurrent_AMSDU_Support; // This indicates Tx A-MSDU capability - u16 nCurrent_AMSDU_MaxSize; // This indicates Tx A-MSDU capability - - - // AMPDU related <2006.08.10 Emily> - u8 bAMPDUEnable; // This indicate Tx A-MPDU capability - u8 bCurrentAMPDUEnable; // This indicate Tx A-MPDU capability - u8 AMPDU_Factor; // This indicate Tx A-MPDU capability - u8 CurrentAMPDUFactor; // This indicate Tx A-MPDU capability - u8 MPDU_Density; // This indicate Tx A-MPDU capability - u8 CurrentMPDUDensity; // This indicate Tx A-MPDU capability +typedef struct _RT_HIGH_THROUGHPUT { + u8 bEnableHT; + u8 bCurrentHTSupport; + /* Tx 40MHz channel capability */ + u8 bRegBW40MHz; + u8 bCurBW40MHz; + /* Tx Short GI for 40Mhz */ + u8 bRegShortGI40MHz; + u8 bCurShortGI40MHz; + /* Tx Short GI for 20MHz */ + u8 bRegShortGI20MHz; + u8 bCurShortGI20MHz; + /* Tx CCK rate capability */ + u8 bRegSuppCCK; + u8 bCurSuppCCK; + + /* 802.11n spec version for "peer" */ + HT_SPEC_VER ePeerHTSpecVer; + + + /* HT related information for "Self" */ + /* This is HT cap element sent to peer STA, which also indicate + * HT Rx capabilities. */ + HT_CAPABILITY_ELE SelfHTCap; + HT_INFORMATION_ELE SelfHTInfo; + + /* HT related information for "Peer" */ + u8 PeerHTCapBuf[32]; + u8 PeerHTInfoBuf[32]; + + + /* A-MSDU related */ + /* This indicates Tx A-MSDU capability */ + u8 bAMSDU_Support; + u16 nAMSDU_MaxSize; + u8 bCurrent_AMSDU_Support; + u16 nCurrent_AMSDU_MaxSize; + + + /* A-MPDU related */ + /* This indicate Tx A-MPDU capability */ + u8 bAMPDUEnable; + u8 bCurrentAMPDUEnable; + u8 AMPDU_Factor; + u8 CurrentAMPDUFactor; + u8 MPDU_Density; + u8 CurrentMPDUDensity; - // Forced A-MPDU enable - HT_AGGRE_MODE_E ForcedAMPDUMode; - u8 ForcedAMPDUFactor; - u8 ForcedMPDUDensity; + /* Forced A-MPDU enable */ + HT_AGGRE_MODE_E ForcedAMPDUMode; + u8 ForcedAMPDUFactor; + u8 ForcedMPDUDensity; - // Forced A-MSDU enable - HT_AGGRE_MODE_E ForcedAMSDUMode; - u16 ForcedAMSDUMaxSize; + /* Forced A-MSDU enable */ + HT_AGGRE_MODE_E ForcedAMSDUMode; + u16 ForcedAMSDUMaxSize; - u8 bForcedShortGI; + u8 bForcedShortGI; - u8 CurrentOpMode; + u8 CurrentOpMode; - // MIMO PS related - u8 SelfMimoPs; - u8 PeerMimoPs; + /* MIMO PS related */ + u8 SelfMimoPs; + u8 PeerMimoPs; - // 40MHz Channel Offset settings. + /* 40MHz Channel Offset settings. */ HT_EXTCHNL_OFFSET CurSTAExtChnlOffset; - u8 bCurTxBW40MHz; // If we use 40 MHz to Tx - u8 PeerBandwidth; - - // For Bandwidth Switching - u8 bSwBwInProgress; - CHNLOP ChnlOp; // software switching channel in progress. By Bruce, 2008-02-15. - u8 SwBwStep; - //RT_TIMER SwBwTimer; - struct timer_list SwBwTimer; - - // For Realtek proprietary A-MPDU factor for aggregation - u8 bRegRT2RTAggregation; - u8 bCurrentRT2RTAggregation; - u8 bCurrentRT2RTLongSlotTime; - u8 szRT2RTAggBuffer[10]; - - // Rx Reorder control - u8 bRegRxReorderEnable; - u8 bCurRxReorderEnable; - u8 RxReorderWinSize; - u8 RxReorderPendingTime; - u16 RxReorderDropCounter; + u8 bCurTxBW40MHz; /* If we use 40 MHz to Tx */ + u8 PeerBandwidth; + + /* For Bandwidth Switching */ + u8 bSwBwInProgress; + CHNLOP ChnlOp; /* sw switching channel in progress. */ + u8 SwBwStep; + struct timer_list SwBwTimer; + + /* For Realtek proprietary A-MPDU factor for aggregation */ + u8 bRegRT2RTAggregation; + u8 bCurrentRT2RTAggregation; + u8 bCurrentRT2RTLongSlotTime; + u8 szRT2RTAggBuffer[10]; + + /* Rx Reorder control */ + u8 bRegRxReorderEnable; + u8 bCurRxReorderEnable; + u8 RxReorderWinSize; + u8 RxReorderPendingTime; + u16 RxReorderDropCounter; #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE - u8 UsbTxAggrNum; + u8 UsbTxAggrNum; #endif #ifdef USB_RX_AGGREGATION_SUPPORT - u8 UsbRxFwAggrEn; - u8 UsbRxFwAggrPageNum; - u8 UsbRxFwAggrPacketNum; - u8 UsbRxFwAggrTimeout; + u8 UsbRxFwAggrEn; + u8 UsbRxFwAggrPageNum; + u8 UsbRxFwAggrPacketNum; + u8 UsbRxFwAggrTimeout; #endif - // Add for Broadcom(Linksys) IOT. Joseph - u8 bIsPeerBcm; + /* Add for Broadcom(Linksys) IOT. */ + u8 bIsPeerBcm; - // For IOT issue. - u32 IOTAction; -}RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT; + /* For IOT issue. */ + u32 IOTAction; +} RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT; -//------------------------------------------------------------ -// The Data structure is used to keep HT related variable for "each Sta" -// when card is configured as "AP mode" -//------------------------------------------------------------ +/*---------------------------------------------------------------------- + * The Data structure is used to keep HT related variable for "each Sta" + * when card is configured as "AP mode" + *----------------------------------------------------------------------*/ -typedef struct _RT_HTINFO_STA_ENTRY{ +typedef struct _RT_HTINFO_STA_ENTRY { u8 bEnableHT; u8 bSupportCck; @@ -335,56 +326,54 @@ typedef struct _RT_HTINFO_STA_ENTRY{ u8 McsRateSet[16]; -}RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY; +} RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY; -//------------------------------------------------------------ -// The Data structure is used to keep HT related variable for "each AP" -// when card is configured as "STA mode" -//------------------------------------------------------------ +/*--------------------------------------------------------------------- + * The Data structure is used to keep HT related variable for "each AP" + * when card is configured as "STA mode" + *---------------------------------------------------------------------*/ -typedef struct _BSS_HT{ +typedef struct _BSS_HT { u8 bdSupportHT; - // HT related elements - u8 bdHTCapBuf[32]; - u16 bdHTCapLen; - u8 bdHTInfoBuf[32]; - u16 bdHTInfoLen; + /* HT related elements */ + u8 bdHTCapBuf[32]; + u16 bdHTCapLen; + u8 bdHTInfoBuf[32]; + u16 bdHTInfoLen; - HT_SPEC_VER bdHTSpecVer; - //HT_CAPABILITY_ELE bdHTCapEle; - //HT_INFORMATION_ELE bdHTInfoEle; + HT_SPEC_VER bdHTSpecVer; - u8 bdRT2RTAggregation; - u8 bdRT2RTLongSlotTime; -}BSS_HT, *PBSS_HT; + u8 bdRT2RTAggregation; + u8 bdRT2RTLongSlotTime; +} BSS_HT, *PBSS_HT; -typedef struct _MIMO_RSSI{ +typedef struct _MIMO_RSSI { u32 EnableAntenna; u32 AntennaA; u32 AntennaB; u32 AntennaC; u32 AntennaD; u32 Average; -}MIMO_RSSI, *PMIMO_RSSI; +} MIMO_RSSI, *PMIMO_RSSI; -typedef struct _MIMO_EVM{ +typedef struct _MIMO_EVM { u32 EVM1; - u32 EVM2; -}MIMO_EVM, *PMIMO_EVM; + u32 EVM2; +} MIMO_EVM, *PMIMO_EVM; -typedef struct _FALSE_ALARM_STATISTICS{ +typedef struct _FALSE_ALARM_STATISTICS { u32 Cnt_Parity_Fail; - u32 Cnt_Rate_Illegal; + u32 Cnt_Rate_Illegal; u32 Cnt_Crc8_fail; u32 Cnt_all; -}FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS; +} FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS; -#endif //__INC_HTTYPE_H +#endif diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.c b/drivers/staging/rtl8192u/r819xU_cmdpkt.c index f40f9c895f56..7bdcbd39a3b2 100644 --- a/drivers/staging/rtl8192u/r819xU_cmdpkt.c +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.c @@ -494,8 +494,8 @@ static void cmpk_handle_tx_rate_history(struct net_device *dev, u8 *pmsg) * 05/06/2008 amy Create Version 0 porting from windows code. * *---------------------------------------------------------------------------*/ -extern u32 cmpk_message_handle_rx(struct net_device *dev, - struct ieee80211_rx_stats *pstats) +u32 cmpk_message_handle_rx(struct net_device *dev, + struct ieee80211_rx_stats *pstats) { int total_length; u8 cmd_length, exe_cnt = 0; diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.h b/drivers/staging/rtl8192u/r819xU_cmdpkt.h index c79878af7021..52cd437ef7bb 100644 --- a/drivers/staging/rtl8192u/r819xU_cmdpkt.h +++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.h @@ -1,17 +1,17 @@ #ifndef R819XUSB_CMDPKT_H #define R819XUSB_CMDPKT_H /* Different command packet have dedicated message length and definition. */ -#define CMPK_RX_TX_FB_SIZE sizeof(cmpk_txfb_t) //20 -#define CMPK_TX_SET_CONFIG_SIZE sizeof(cmpk_set_cfg_t) //16 -#define CMPK_BOTH_QUERY_CONFIG_SIZE sizeof(cmpk_set_cfg_t) //16 -#define CMPK_RX_TX_STS_SIZE sizeof(cmpk_tx_status_t)// -#define CMPK_RX_DBG_MSG_SIZE sizeof(cmpk_rx_dbginfo_t)// -#define CMPK_TX_RAHIS_SIZE sizeof(cmpk_tx_rahis_t) +#define CMPK_RX_TX_FB_SIZE sizeof(cmpk_txfb_t) /* 20 */ +#define CMPK_TX_SET_CONFIG_SIZE sizeof(cmpk_set_cfg_t) /* 16 */ +#define CMPK_BOTH_QUERY_CONFIG_SIZE sizeof(cmpk_set_cfg_t) /* 16 */ +#define CMPK_RX_TX_STS_SIZE sizeof(cmpk_tx_status_t) +#define CMPK_RX_DBG_MSG_SIZE sizeof(cmpk_rx_dbginfo_t) +#define CMPK_TX_RAHIS_SIZE sizeof(cmpk_tx_rahis_t) /* 2008/05/08 amy For USB constant. */ -#define ISR_TxBcnOk BIT27 // Transmit Beacon OK -#define ISR_TxBcnErr BIT26 // Transmit Beacon Error -#define ISR_BcnTimerIntr BIT13 // Beacon Timer Interrupt +#define ISR_TxBcnOk BIT27 /* Transmit Beacon OK */ +#define ISR_TxBcnErr BIT26 /* Transmit Beacon Error */ +#define ISR_BcnTimerIntr BIT13 /* Beacon Timer Interrupt */ /* Define element ID of command packet. */ @@ -20,180 +20,172 @@ /* Define different command packet structure. */ /* 1. RX side: TX feedback packet. */ typedef struct tag_cmd_pkt_tx_feedback { - // DWORD 0 + /* DWORD 0 */ u8 element_id; /* Command packet type. */ u8 length; /* Command packet length. */ - /* 2007/07/05 MH Change tx feedback info field. */ + /* Change tx feedback info field. */ /*------TX Feedback Info Field */ - u8 TID:4; /* */ - u8 fail_reason:3; /* */ + u8 TID:4; + u8 fail_reason:3; u8 tok:1; /* Transmit ok. */ - u8 reserve1:4; /* */ - u8 pkt_type:2; /* */ - u8 bandwidth:1; /* */ - u8 qos_pkt:1; /* */ + u8 reserve1:4; + u8 pkt_type:2; + u8 bandwidth:1; + u8 qos_pkt:1; - // DWORD 1 - u8 reserve2; /* */ + /* DWORD 1 */ + u8 reserve2; /*------TX Feedback Info Field */ - u8 retry_cnt; /* */ - u16 pkt_id; /* */ + u8 retry_cnt; + u16 pkt_id; - // DWORD 3 - u16 seq_num; /* */ + /* DWORD 3 */ + u16 seq_num; u8 s_rate; /* Start rate. */ u8 f_rate; /* Final rate. */ - // DWORD 4 - u8 s_rts_rate; /* */ - u8 f_rts_rate; /* */ - u16 pkt_length; /* */ + /* DWORD 4 */ + u8 s_rts_rate; + u8 f_rts_rate; + u16 pkt_length; - // DWORD 5 - u16 reserve3; /* */ - u16 duration; /* */ -}cmpk_txfb_t; + /* DWORD 5 */ + u16 reserve3; + u16 duration; +} cmpk_txfb_t; /* 2. RX side: Interrupt status packet. It includes Beacon State, - Beacon Timer Interrupt and other useful informations in MAC ISR Reg. */ + * Beacon Timer Interrupt and other useful informations in MAC ISR Reg. */ typedef struct tag_cmd_pkt_interrupt_status { u8 element_id; /* Command packet type. */ u8 length; /* Command packet length. */ u16 reserve; - u32 interrupt_status; /* Interrupt Status. */ -}cmpk_intr_sta_t; + u32 interrupt_status; /* Interrupt Status. */ +} cmpk_intr_sta_t; /* 3. TX side: Set configuration packet. */ typedef struct tag_cmd_pkt_set_configuration { u8 element_id; /* Command packet type. */ u8 length; /* Command packet length. */ - u16 reserve1; /* */ + u16 reserve1; + /* Configuration info. */ u8 cfg_reserve1:3; - u8 cfg_size:2; /* Configuration info. */ - u8 cfg_type:2; /* Configuration info. */ - u8 cfg_action:1; /* Configuration info. */ - u8 cfg_reserve2; /* Configuration info. */ - u8 cfg_page:4; /* Configuration info. */ - u8 cfg_reserve3:4; /* Configuration info. */ - u8 cfg_offset; /* Configuration info. */ - u32 value; /* */ - u32 mask; /* */ -}cmpk_set_cfg_t; + u8 cfg_size:2; + u8 cfg_type:2; + u8 cfg_action:1; + u8 cfg_reserve2; + u8 cfg_page:4; + u8 cfg_reserve3:4; + u8 cfg_offset; + u32 value; + u32 mask; +} cmpk_set_cfg_t; /* 4. Both side : TX/RX query configuraton packet. The query structure is the same as set configuration. */ #define cmpk_query_cfg_t cmpk_set_cfg_t /* 5. Multi packet feedback status. */ -typedef struct tag_tx_stats_feedback { // PJ quick rxcmd 09042007 - // For endian transfer --> Driver will not the same as firmware structure. - // DW 0 +typedef struct tag_tx_stats_feedback { + /* For endian transfer --> Driver will not the same as + firmware structure. */ + /* DW 0 */ u16 reserve1; - u8 length; // Command packet length - u8 element_id; // Command packet type + u8 length; /* Command packet length */ + u8 element_id; /* Command packet type */ - // DW 1 - u16 txfail; // Tx Fail count - u16 txok; // Tx ok count + /* DW 1 */ + u16 txfail; /* Tx fail count */ + u16 txok; /* Tx ok count */ - // DW 2 - u16 txmcok; // tx multicast - u16 txretry; // Tx Retry count + /* DW 2 */ + u16 txmcok; /* Tx multicast */ + u16 txretry; /* Tx retry count */ - // DW 3 - u16 txucok; // tx unicast - u16 txbcok; // tx broadcast + /* DW 3 */ + u16 txucok; /* Tx unicast */ + u16 txbcok; /* Tx broadcast */ - // DW 4 - u16 txbcfail; // - u16 txmcfail; // + /* DW 4 */ + u16 txbcfail; + u16 txmcfail; - // DW 5 - u16 reserve2; // - u16 txucfail; // + /* DW 5 */ + u16 reserve2; + u16 txucfail; - // DW 6-8 + /* DW 6-8 */ u32 txmclength; u32 txbclength; u32 txuclength; - // DW 9 + /* DW 9 */ u16 reserve3_23; u8 reserve3_1; u8 rate; -}__attribute__((packed)) cmpk_tx_status_t; +} __packed cmpk_tx_status_t; /* 6. Debug feedback message. */ -/* 2007/10/23 MH Define RX debug message */ +/* Define RX debug message */ typedef struct tag_rx_debug_message_feedback { - // For endian transfer --> for driver - // DW 0 + /* For endian transfer --> for driver */ + /* DW 0 */ u16 reserve1; - u8 length; // Command packet length - u8 element_id; // Command packet type + u8 length; /* Command packet length */ + u8 element_id; /* Command packet type */ - // DW 1-?? - // Variable debug message. + /* DW 1-?? */ + /* Variable debug message. */ -}cmpk_rx_dbginfo_t; +} cmpk_rx_dbginfo_t; -/* 2008/03/20 MH Define transmit rate history. For big endian format. */ +/* Define transmit rate history. For big endian format. */ typedef struct tag_tx_rate_history { - // For endian transfer --> for driver - // DW 0 - u8 element_id; // Command packet type - u8 length; // Command packet length + /* For endian transfer --> for driver */ + /* DW 0 */ + u8 element_id; /* Command packet type */ + u8 length; /* Command packet length */ u16 reserved1; - // DW 1-2 CCK rate counter + /* DW 1-2 CCK rate counter */ u16 cck[4]; - // DW 3-6 + /* DW 3-6 */ u16 ofdm[8]; - // DW 7-14 - //UINT16 MCS_BW0_SG0[16]; - - // DW 15-22 - //UINT16 MCS_BW1_SG0[16]; - - // DW 23-30 - //UINT16 MCS_BW0_SG1[16]; - - // DW 31-38 - //UINT16 MCS_BW1_SG1[16]; - - // DW 7-14 BW=0 SG=0 - // DW 15-22 BW=1 SG=0 - // DW 23-30 BW=0 SG=1 - // DW 31-38 BW=1 SG=1 + /* DW 7-14 BW=0 SG=0 + * DW 15-22 BW=1 SG=0 + * DW 23-30 BW=0 SG=1 + * DW 31-38 BW=1 SG=1 + */ u16 ht_mcs[4][16]; -}__attribute__((packed)) cmpk_tx_rahis_t; - -typedef enum tag_command_packet_directories -{ - RX_TX_FEEDBACK = 0, - RX_INTERRUPT_STATUS = 1, - TX_SET_CONFIG = 2, - BOTH_QUERY_CONFIG = 3, - RX_TX_STATUS = 4, - RX_DBGINFO_FEEDBACK = 5, - RX_TX_PER_PKT_FEEDBACK = 6, - RX_TX_RATE_HISTORY = 7, - RX_CMD_ELE_MAX -}cmpk_element_e; - -typedef enum _rt_status{ +} __packed cmpk_tx_rahis_t; + +typedef enum tag_command_packet_directories { + RX_TX_FEEDBACK = 0, + RX_INTERRUPT_STATUS = 1, + TX_SET_CONFIG = 2, + BOTH_QUERY_CONFIG = 3, + RX_TX_STATUS = 4, + RX_DBGINFO_FEEDBACK = 5, + RX_TX_PER_PKT_FEEDBACK = 6, + RX_TX_RATE_HISTORY = 7, + RX_CMD_ELE_MAX +} cmpk_element_e; + +typedef enum _rt_status { RT_STATUS_SUCCESS, RT_STATUS_FAILURE, RT_STATUS_PENDING, RT_STATUS_RESOURCE -}rt_status,*prt_status; +} rt_status, *prt_status; -extern u32 cmpk_message_handle_rx(struct net_device *dev, struct ieee80211_rx_stats *pstats); -extern rt_status SendTxCommandPacket( struct net_device *dev, void *pData, u32 DataLen); +extern u32 cmpk_message_handle_rx(struct net_device *dev, + struct ieee80211_rx_stats *pstats); +extern rt_status SendTxCommandPacket(struct net_device *dev, + void *pData, u32 DataLen); #endif diff --git a/drivers/staging/rtl8192u/r819xU_phy.c b/drivers/staging/rtl8192u/r819xU_phy.c index 17ac1202c906..39cd426bc5e5 100644 --- a/drivers/staging/rtl8192u/r819xU_phy.c +++ b/drivers/staging/rtl8192u/r819xU_phy.c @@ -1713,7 +1713,7 @@ void InitialGain819xUsb(struct net_device *dev, u8 Operation) queue_delayed_work(priv->priv_wq, &priv->initialgain_operate_wq, 0); } -extern void InitialGainOperateWorkItemCallBack(struct work_struct *work) +void InitialGainOperateWorkItemCallBack(struct work_struct *work) { struct delayed_work *dwork = container_of(work, struct delayed_work, work); diff --git a/drivers/staging/rtl8192u/r819xU_phy.h b/drivers/staging/rtl8192u/r819xU_phy.h index f3c352a10fe0..66cbe3f9cafd 100644 --- a/drivers/staging/rtl8192u/r819xU_phy.h +++ b/drivers/staging/rtl8192u/r819xU_phy.h @@ -23,7 +23,7 @@ typedef struct _SwChnlCmd { u32 Para1; u32 Para2; u32 msDelay; -} __attribute__ ((packed)) SwChnlCmd; +} __packed SwChnlCmd; extern u32 rtl819XMACPHY_Array_PG[]; extern u32 rtl819XPHY_REG_1T2RArray[]; diff --git a/drivers/staging/sb105x/sb_mp_register.h b/drivers/staging/sb105x/sb_mp_register.h index 304e1bcd1e3b..16de497415ee 100644 --- a/drivers/staging/sb105x/sb_mp_register.h +++ b/drivers/staging/sb105x/sb_mp_register.h @@ -15,8 +15,8 @@ #ifndef UART_SB105X_H #define UART_SB105X_H -/* - * option register +/* + * option register */ /* Device Information Register */ diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c index 6037ec180d90..ba199ffff178 100644 --- a/drivers/staging/sm7xxfb/sm7xxfb.c +++ b/drivers/staging/sm7xxfb/sm7xxfb.c @@ -130,7 +130,8 @@ static int __init sm7xx_vga_setup(char *options) for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) { if (strstr(options, vesa_mode_table[i].index)) { smtc_scr_info.lfb_width = vesa_mode_table[i].lfb_width; - smtc_scr_info.lfb_height = vesa_mode_table[i].lfb_height; + smtc_scr_info.lfb_height = + vesa_mode_table[i].lfb_height; smtc_scr_info.lfb_depth = vesa_mode_table[i].lfb_depth; return 0; } diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c index 70231b6dabba..445a3fda380e 100644 --- a/drivers/staging/speakup/varhandlers.c +++ b/drivers/staging/speakup/varhandlers.c @@ -280,7 +280,7 @@ int spk_set_mask_bits(const char *input, const int which, const int how) if (!cp) cp = spk_punc_info[which].value; else { - for ( ; *cp; cp++) { + for (; *cp; cp++) { if (*cp < SPACE) break; if (mask < PUNC) { @@ -294,11 +294,11 @@ int spk_set_mask_bits(const char *input, const int which, const int how) cp = (u_char *)input; } if (how&2) { - for ( ; *cp; cp++) + for (; *cp; cp++) if (*cp > SPACE) spk_chartab[*cp] |= mask; } else { - for ( ; *cp; cp++) + for (; *cp; cp++) if (*cp > SPACE) spk_chartab[*cp] &= ~mask; } diff --git a/drivers/staging/vt6655/aes_ccmp.c b/drivers/staging/vt6655/aes_ccmp.c index fc056fc61995..82b0bd1c056a 100644 --- a/drivers/staging/vt6655/aes_ccmp.c +++ b/drivers/staging/vt6655/aes_ccmp.c @@ -46,7 +46,7 @@ * SBOX Table */ -unsigned char sbox_table[256] = +static unsigned char sbox_table[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, @@ -66,7 +66,7 @@ unsigned char sbox_table[256] = 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; -unsigned char dot2_table[256] = { +static unsigned char dot2_table[256] = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, @@ -85,7 +85,7 @@ unsigned char dot2_table[256] = { 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5 }; -unsigned char dot3_table[256] = { +static unsigned char dot3_table[256] = { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, @@ -110,7 +110,7 @@ unsigned char dot3_table[256] = { /*--------------------- Export Functions --------------------------*/ -void xor_128(unsigned char *a, unsigned char *b, unsigned char *out) +static void xor_128(unsigned char *a, unsigned char *b, unsigned char *out) { unsigned long *dwPtrA = (unsigned long *)a; unsigned long *dwPtrB = (unsigned long *)b; @@ -122,7 +122,7 @@ void xor_128(unsigned char *a, unsigned char *b, unsigned char *out) (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); } -void xor_32(unsigned char *a, unsigned char *b, unsigned char *out) +static void xor_32(unsigned char *a, unsigned char *b, unsigned char *out) { unsigned long *dwPtrA = (unsigned long *)a; unsigned long *dwPtrB = (unsigned long *)b; @@ -131,7 +131,7 @@ void xor_32(unsigned char *a, unsigned char *b, unsigned char *out) (*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++); } -void AddRoundKey(unsigned char *key, int round) +static void AddRoundKey(unsigned char *key, int round) { unsigned char sbox_key[4]; unsigned char rcon_table[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; @@ -149,7 +149,7 @@ void AddRoundKey(unsigned char *key, int round) xor_32(&key[12], &key[8], &key[12]); } -void SubBytes(unsigned char *in, unsigned char *out) +static void SubBytes(unsigned char *in, unsigned char *out) { int i; @@ -158,7 +158,7 @@ void SubBytes(unsigned char *in, unsigned char *out) } } -void ShiftRows(unsigned char *in, unsigned char *out) +static void ShiftRows(unsigned char *in, unsigned char *out) { out[0] = in[0]; out[1] = in[5]; @@ -178,7 +178,7 @@ void ShiftRows(unsigned char *in, unsigned char *out) out[15] = in[11]; } -void MixColumns(unsigned char *in, unsigned char *out) +static void MixColumns(unsigned char *in, unsigned char *out) { out[0] = dot2_table[in[0]] ^ dot3_table[in[1]] ^ in[2] ^ in[3]; out[1] = in[0] ^ dot2_table[in[1]] ^ dot3_table[in[2]] ^ in[3]; @@ -186,7 +186,7 @@ void MixColumns(unsigned char *in, unsigned char *out) out[3] = dot3_table[in[0]] ^ in[1] ^ in[2] ^ dot2_table[in[3]]; } -void AESv128(unsigned char *key, unsigned char *data, unsigned char *ciphertext) +static void AESv128(unsigned char *key, unsigned char *data, unsigned char *ciphertext) { int i; int round; diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c index fdd63b60b7c0..aab0012bba92 100644 --- a/drivers/staging/vt6655/hostap.c +++ b/drivers/staging/vt6655/hostap.c @@ -730,7 +730,7 @@ int vt6655_hostap_ioctl(PSDevice pDevice, struct iw_point *p) p->length > VIAWGET_HOSTAPD_MAX_BUF_SIZE || !p->pointer) return -EINVAL; - param = kmalloc((int)p->length, (int)GFP_KERNEL); + param = kmalloc((int)p->length, GFP_KERNEL); if (param == NULL) return -ENOMEM; diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c index 6948984a25ab..ce173cc16c19 100644 --- a/drivers/staging/vt6655/rf.c +++ b/drivers/staging/vt6655/rf.c @@ -55,7 +55,7 @@ /*--------------------- Static Variables --------------------------*/ -const unsigned long dwAL2230InitTable[CB_AL2230_INIT_SEQ] = { +static const unsigned long dwAL2230InitTable[CB_AL2230_INIT_SEQ] = { 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // 0x01A00200+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // @@ -73,7 +73,7 @@ const unsigned long dwAL2230InitTable[CB_AL2230_INIT_SEQ] = { 0x00580F00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW }; -const unsigned long dwAL2230ChannelTable0[CB_MAX_CHANNEL] = { +static const unsigned long dwAL2230ChannelTable0[CB_MAX_CHANNEL] = { 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz 0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz @@ -90,7 +90,7 @@ const unsigned long dwAL2230ChannelTable0[CB_MAX_CHANNEL] = { 0x03E7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW // channel = 14, Tf = 2412M }; -const unsigned long dwAL2230ChannelTable1[CB_MAX_CHANNEL] = { +static const unsigned long dwAL2230ChannelTable1[CB_MAX_CHANNEL] = { 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz @@ -107,7 +107,7 @@ const unsigned long dwAL2230ChannelTable1[CB_MAX_CHANNEL] = { 0x06666100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW // channel = 14, Tf = 2412M }; -unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = { +static unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = { 0x04040900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, 0x04041900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, 0x04042900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, @@ -177,7 +177,7 @@ unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = { //{{ RobertYu:20050104 // 40MHz reference frequency // Need to Pull PLLON(PE3) low when writing channel registers through 3-wire. -const unsigned long dwAL7230InitTable[CB_AL7230_INIT_SEQ] = { +static const unsigned long dwAL7230InitTable[CB_AL7230_INIT_SEQ] = { 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a 0x841FF200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 451FE2 @@ -200,7 +200,7 @@ const unsigned long dwAL7230InitTable[CB_AL7230_INIT_SEQ] = { 0x1ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // Need modify for 11a: 12BACF }; -const unsigned long dwAL7230InitTableAMode[CB_AL7230_INIT_SEQ] = { +static const unsigned long dwAL7230InitTableAMode[CB_AL7230_INIT_SEQ] = { 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g 0x451FE200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g @@ -219,7 +219,7 @@ const unsigned long dwAL7230InitTableAMode[CB_AL7230_INIT_SEQ] = { 0x12BACF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // Need modify for 11b/g }; -const unsigned long dwAL7230ChannelTable0[CB_MAX_CHANNEL] = { +static const unsigned long dwAL7230ChannelTable0[CB_MAX_CHANNEL] = { 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz @@ -285,7 +285,7 @@ const unsigned long dwAL7230ChannelTable0[CB_MAX_CHANNEL] = { 0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // channel = 165, Tf = 5825MHz (56) }; -const unsigned long dwAL7230ChannelTable1[CB_MAX_CHANNEL] = { +static const unsigned long dwAL7230ChannelTable1[CB_MAX_CHANNEL] = { 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz @@ -349,7 +349,7 @@ const unsigned long dwAL7230ChannelTable1[CB_MAX_CHANNEL] = { 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // channel = 165, Tf = 5825MHz (56) }; -const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = { +static const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = { 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz @@ -428,7 +428,7 @@ const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = { * Return Value: true if succeeded; false if failed. * */ -bool s_bAL7230Init(unsigned long dwIoBase) +static bool s_bAL7230Init(unsigned long dwIoBase) { int ii; bool bResult; @@ -471,7 +471,7 @@ bool s_bAL7230Init(unsigned long dwIoBase) } // Need to Pull PLLON low when writing channel registers through 3-wire interface -bool s_bAL7230SelectChannel(unsigned long dwIoBase, unsigned char byChannel) +static bool s_bAL7230SelectChannel(unsigned long dwIoBase, unsigned char byChannel) { bool bResult; @@ -631,7 +631,7 @@ bool IFRFbWriteEmbedded(unsigned long dwIoBase, unsigned long dwData) * Return Value: true if succeeded; false if failed. * */ -bool RFbAL2230Init(unsigned long dwIoBase) +static bool RFbAL2230Init(unsigned long dwIoBase) { int ii; bool bResult; @@ -678,7 +678,7 @@ bool RFbAL2230Init(unsigned long dwIoBase) return bResult; } -bool RFbAL2230SelectChannel(unsigned long dwIoBase, unsigned char byChannel) +static bool RFbAL2230SelectChannel(unsigned long dwIoBase, unsigned char byChannel) { bool bResult; @@ -776,36 +776,6 @@ bool RFbInit( } /* - * Description: RF ShutDown function - * - * Parameters: - * In: - * byBBType - * byRFType - * Out: - * none - * - * Return Value: true if succeeded; false if failed. - * - */ -bool RFbShutDown( - PSDevice pDevice -) -{ - bool bResult = true; - - switch (pDevice->byRFType) { - case RF_AIROHA7230: - bResult = IFRFbWriteEmbedded(pDevice->PortOffset, 0x1ABAEF00 + (BY_AL7230_REG_LEN << 3) + IFREGCTL_REGW); - break; - default: - bResult = true; - break; - } - return bResult; -} - -/* * Description: Select channel * * Parameters: diff --git a/drivers/staging/vt6655/wroute.c b/drivers/staging/vt6655/wroute.c index b61328fbee87..85302c5e2bac 100644 --- a/drivers/staging/vt6655/wroute.c +++ b/drivers/staging/vt6655/wroute.c @@ -179,7 +179,7 @@ bool ROUTEbRelay(PSDevice pDevice, unsigned char *pbySkbData, unsigned int uData pHeadTD = pHeadTD->next; } - pLastTD->pTDInfo->skb = 0; + pLastTD->pTDInfo->skb = NULL; pLastTD->pTDInfo->byFlags = 0; pDevice->apCurrTD[TYPE_AC0DMA] = pHeadTD; diff --git a/drivers/staging/vt6655/wroute.h b/drivers/staging/vt6655/wroute.h index 5ecc190ae775..3abc1d36f89d 100644 --- a/drivers/staging/vt6655/wroute.h +++ b/drivers/staging/vt6655/wroute.h @@ -41,4 +41,4 @@ bool ROUTEbRelay(PSDevice pDevice, unsigned char *pbySkbData, unsigned int uDataLen, unsigned int uNodeIndex); -#endif // __WROUTE_H__ +#endif /* __WROUTE_H__ */ diff --git a/drivers/staging/vt6656/bssdb.c b/drivers/staging/vt6656/bssdb.c index ae0438a43ea5..dad3f8c78e21 100644 --- a/drivers/staging/vt6656/bssdb.c +++ b/drivers/staging/vt6656/bssdb.c @@ -57,6 +57,7 @@ #include "control.h" #include "rndis.h" #include "iowpa.h" +#include "power.h" static int msglevel =MSG_LEVEL_INFO; //static int msglevel =MSG_LEVEL_DEBUG; @@ -824,6 +825,9 @@ void BSSvSecondCallBack(struct work_struct *work) u32 uNonShortSlotSTACnt = 0; u32 uLongPreambleSTACnt = 0; + if (pDevice->Flags & fMP_DISCONNECTED) + return; + spin_lock_irq(&pDevice->lock); pDevice->uAssocCount = 0; @@ -1121,10 +1125,22 @@ else { } } - if (pDevice->bLinkPass == true) { - if (netif_queue_stopped(pDevice->dev)) - netif_wake_queue(pDevice->dev); - } + if (pDevice->bLinkPass == true) { + if (pMgmt->eAuthenMode < WMAC_AUTH_WPA || + pDevice->fWPA_Authened == true) { + if (++pDevice->tx_data_time_out > 40) { + pDevice->tx_trigger = true; + + PSbSendNullPacket(pDevice); + + pDevice->tx_trigger = false; + pDevice->tx_data_time_out = 0; + } + } + + if (netif_queue_stopped(pDevice->dev)) + netif_wake_queue(pDevice->dev); + } spin_unlock_irq(&pDevice->lock); diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h index fa1cefb2f2af..62b7de19b371 100644 --- a/drivers/staging/vt6656/device.h +++ b/drivers/staging/vt6656/device.h @@ -579,6 +579,9 @@ struct vnt_private { u8 abyOFDMAPwrTbl[42]; u16 wCurrentRate; + u16 tx_rate_fb0; + u16 tx_rate_fb1; + u16 wRTSThreshold; u16 wFragmentationThreshold; u8 byShortRetryLimit; @@ -711,11 +714,8 @@ struct vnt_private { /* One second callback */ struct delayed_work second_callback_work; - struct timer_list sTimerTxData; - unsigned long nTxDataTimeCout; - int fTxDataInSleep; - int IsTxDataTrigger; - + u8 tx_data_time_out; + bool tx_trigger; int fWPA_Authened; /*is WPA/WPA-PSK or WPA2/WPA2-PSK authen?? */ u8 byReAssocCount; u8 byLinkWaitCount; diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index 82d7c1d09ef6..75dc92d64056 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -1339,6 +1339,9 @@ void RXvWorkItem(struct work_struct *work) int ntStatus; struct vnt_rcb *pRCB = NULL; + if (pDevice->Flags & fMP_DISCONNECTED) + return; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Polling Thread\n"); spin_lock_irq(&pDevice->lock); @@ -1398,6 +1401,9 @@ void RXvMngWorkItem(struct work_struct *work) struct vnt_rx_mgmt *pRxPacket; int bReAllocSkb = false; + if (pDevice->Flags & fMP_DISCONNECTED) + return; + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Rx Mng Thread\n"); spin_lock_irq(&pDevice->lock); diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c index a1dc3a4cfd9c..cd2ea76c8b1e 100644 --- a/drivers/staging/vt6656/firmware.c +++ b/drivers/staging/vt6656/firmware.c @@ -35,8 +35,8 @@ #include "control.h" #include "rndis.h" -static int msglevel =MSG_LEVEL_INFO; -//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel = MSG_LEVEL_INFO; +/* static int msglevel = MSG_LEVEL_DEBUG; */ #define FIRMWARE_VERSION 0x133 /* version 1.51 */ #define FIRMWARE_NAME "vntwusb.fw" @@ -72,18 +72,17 @@ int FIRMWAREbDownload(struct vnt_private *pDevice) memcpy(pBuffer, fw->data + ii, wLength); NdisStatus = CONTROLnsRequestOutAsyn(pDevice, - 0, - 0x1200+ii, - 0x0000, - wLength, - pBuffer - ); + 0, + 0x1200+ii, + 0x0000, + wLength, + pBuffer); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Download firmware...%d %zu\n", ii, fw->size); if (NdisStatus != STATUS_SUCCESS) goto free_fw; - } + } result = true; free_fw: @@ -101,48 +100,47 @@ int FIRMWAREbBrach2Sram(struct vnt_private *pDevice) { int NdisStatus; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Branch to Sram\n"); - - NdisStatus = CONTROLnsRequestOut(pDevice, - 1, - 0x1200, - 0x0000, - 0, - NULL - ); - - if (NdisStatus != STATUS_SUCCESS) { - return (false); - } else { - return (true); - } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Branch to Sram\n"); + + NdisStatus = CONTROLnsRequestOut(pDevice, + 1, + 0x1200, + 0x0000, + 0, + NULL); + if (NdisStatus != STATUS_SUCCESS) + return false; + else + return true; } int FIRMWAREbCheckVersion(struct vnt_private *pDevice) { int ntStatus; - ntStatus = CONTROLnsRequestIn(pDevice, - MESSAGE_TYPE_READ, - 0, - MESSAGE_REQUEST_VERSION, - 2, - (u8 *) &(pDevice->wFirmwareVersion)); - - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n", pDevice->wFirmwareVersion); - if (ntStatus != STATUS_SUCCESS) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Invalid.\n"); - return false; - } - if (pDevice->wFirmwareVersion == 0xFFFF) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"In Loader.\n"); - return false; - } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n", pDevice->wFirmwareVersion); - if (pDevice->wFirmwareVersion < FIRMWARE_VERSION) { - // branch to loader for download new firmware - FIRMWAREbBrach2Sram(pDevice); - return false; - } - return true; + ntStatus = CONTROLnsRequestIn(pDevice, + MESSAGE_TYPE_READ, + 0, + MESSAGE_REQUEST_VERSION, + 2, + (u8 *) &(pDevice->wFirmwareVersion)); + + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n", + pDevice->wFirmwareVersion); + if (ntStatus != STATUS_SUCCESS) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Invalid.\n"); + return false; + } + if (pDevice->wFirmwareVersion == 0xFFFF) { + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"In Loader.\n"); + return false; + } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n", + pDevice->wFirmwareVersion); + if (pDevice->wFirmwareVersion < FIRMWARE_VERSION) { + /* branch to loader for download new firmware */ + FIRMWAREbBrach2Sram(pDevice); + return false; + } + return true; } diff --git a/drivers/staging/vt6656/iwctl.c b/drivers/staging/vt6656/iwctl.c index 59688881a9a0..63917abbbd00 100644 --- a/drivers/staging/vt6656/iwctl.c +++ b/drivers/staging/vt6656/iwctl.c @@ -60,7 +60,7 @@ struct iw_statistics *iwctl_get_wireless_stats(struct net_device *dev) pDevice->wstats.status = pDevice->eOPMode; if (pDevice->scStatistic.LinkQuality > 100) pDevice->scStatistic.LinkQuality = 100; - pDevice->wstats.qual.qual =(u8)pDevice->scStatistic.LinkQuality; + pDevice->wstats.qual.qual = (u8)pDevice->scStatistic.LinkQuality; RFvRSSITodBm(pDevice, (u8)(pDevice->uCurrRSSI), &ldBm); pDevice->wstats.qual.level = ldBm; pDevice->wstats.qual.noise = 0; @@ -190,7 +190,7 @@ int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info, return -EAGAIN; } pBSS = &(pMgmt->sBSSList[0]); - for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) { + for (ii = 0, jj = 0; jj < MAX_BSS_NUM; jj++) { if (current_ev >= end_buf) break; pBSS = &(pMgmt->sBSSList[jj]); @@ -225,7 +225,7 @@ int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info, iwe.u.freq.m = pBSS->uChannel; iwe.u.freq.e = 0; iwe.u.freq.i = 0; - 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); { int f = (int)pBSS->uChannel - 1; if (f < 0) @@ -400,7 +400,7 @@ int iwctl_siwmode(struct net_device *dev, struct iw_request_info *info, if (pDevice->flags & DEVICE_FLAGS_OPENED) pDevice->bCommit = true; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to ad-hoc \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to ad-hoc\n"); break; case IW_MODE_AUTO: case IW_MODE_INFRA: @@ -409,7 +409,7 @@ int iwctl_siwmode(struct net_device *dev, struct iw_request_info *info, if (pDevice->flags & DEVICE_FLAGS_OPENED) pDevice->bCommit = true; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to infrastructure \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to infrastructure\n"); break; case IW_MODE_MASTER: @@ -422,7 +422,7 @@ int iwctl_siwmode(struct net_device *dev, struct iw_request_info *info, if (pDevice->flags & DEVICE_FLAGS_OPENED) pDevice->bCommit = true; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to Access Point \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set mode to Access Point\n"); break; case IW_MODE_REPEAT: @@ -786,8 +786,8 @@ int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info, if (wrq->flags == 0) { // Just send an empty SSID list memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1); - memset(pMgmt->abyDesireBSSID, 0xFF,6); - PRINT_K("set essid to 'any' \n"); + memset(pMgmt->abyDesireBSSID, 0xFF, 6); + PRINT_K("set essid to 'any'\n"); // Unknown desired AP, so here need not associate?? return 0; } else { @@ -798,15 +798,15 @@ int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info, memcpy(pItemSSID->abySSID, extra, wrq->length); if (pItemSSID->abySSID[wrq->length] == '\0') { - if (wrq->length>0) + if (wrq->length > 0) pItemSSID->len = wrq->length; } else { pItemSSID->len = wrq->length; } - PRINT_K("set essid to %s \n", pItemSSID->abySSID); + PRINT_K("set essid to %s\n", pItemSSID->abySSID); // mike: need clear desiredBSSID - if (pItemSSID->len==0) { + if (pItemSSID->len == 0) { memset(pMgmt->abyDesireBSSID, 0xFF, 6); return 0; } @@ -860,7 +860,7 @@ int iwctl_siwessid(struct net_device *dev, struct iw_request_info *info, return 0; } - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set essid = %s \n", pItemSSID->abySSID); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "set essid = %s\n", pItemSSID->abySSID); } if (pDevice->flags & DEVICE_FLAGS_OPENED) @@ -893,7 +893,7 @@ int iwctl_giwessid(struct net_device *dev, struct iw_request_info *info, memcpy(extra, pItemSSID->abySSID, pItemSSID->len); extra[pItemSSID->len] = '\0'; - wrq->length = pItemSSID->len; + wrq->length = pItemSSID->len; wrq->flags = 1; // active return 0; @@ -915,7 +915,7 @@ int iwctl_siwrate(struct net_device *dev, struct iw_request_info *info, 0x60, 0x6C, 0x90 }; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRATE \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWRATE\n"); if (!(pDevice->flags & DEVICE_FLAGS_OPENED)) { rc = -EINVAL; return rc; @@ -953,7 +953,7 @@ int iwctl_siwrate(struct net_device *dev, struct iw_request_info *info, } // Check that it is valid // brate is index of abySupportedRates[] - if (brate > 13 ) { + if (brate > 13) { rc = -EINVAL; return rc; } @@ -967,7 +967,7 @@ int iwctl_siwrate(struct net_device *dev, struct iw_request_info *info, pDevice->uConnectionRate = 3; } else { pDevice->uConnectionRate = brate; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Fixed to Rate %d \n", pDevice->uConnectionRate); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Fixed to Rate %d\n", pDevice->uConnectionRate); } } else { pDevice->bFixRate = false; @@ -1017,7 +1017,7 @@ int iwctl_giwrate(struct net_device *dev, struct iw_request_info *info, if (pDevice->byBBType == BB_TYPE_11A) brate = 0x6C; } - if (pDevice->uConnectionRate == 13) + if (pDevice->uConnectionRate == 13) brate = abySupportedRates[pDevice->wCurrentRate]; wrq->value = brate * 500000; // If more than one rate, set auto @@ -1286,7 +1286,7 @@ int iwctl_giwencode(struct net_device *dev, struct iw_request_info *info, if (index < 1) { // get default key if (pDevice->byKeyIndex < WLAN_WEP_NKEYS) index = pDevice->byKeyIndex; - else + else index = 0; } else { index--; @@ -1366,14 +1366,14 @@ int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info, switch (wrq->flags & IW_POWER_MODE) { case IW_POWER_UNICAST_R: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_UNICAST_R \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_UNICAST_R\n"); rc = -EINVAL; break; case IW_POWER_ALL_R: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ALL_R \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ALL_R\n"); rc = -EINVAL; case IW_POWER_ON: - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ON \n"); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_ON\n"); break; default: rc = -EINVAL; @@ -1465,7 +1465,7 @@ int iwctl_siwauth(struct net_device *dev, struct iw_request_info *info, case IW_AUTH_CIPHER_PAIRWISE: pairwise = wrq->value; PRINT_K("iwctl_siwauth:set pairwise=%d\n", pairwise); - if (pairwise == IW_AUTH_CIPHER_CCMP){ + if (pairwise == IW_AUTH_CIPHER_CCMP) { pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; } else if (pairwise == IW_AUTH_CIPHER_TKIP) { pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; @@ -1490,13 +1490,13 @@ int iwctl_siwauth(struct net_device *dev, struct iw_request_info *info, } break; case IW_AUTH_KEY_MGMT: - PRINT_K("iwctl_siwauth(wpa_version=%d):set KEY_MGMT=%d\n", wpa_version,wrq->value); - if (wpa_version == IW_AUTH_WPA_VERSION_WPA2){ + PRINT_K("iwctl_siwauth(wpa_version=%d):set KEY_MGMT=%d\n", wpa_version, wrq->value); + if (wpa_version == IW_AUTH_WPA_VERSION_WPA2) { if (wrq->value == IW_AUTH_KEY_MGMT_PSK) pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK; else pMgmt->eAuthenMode = WMAC_AUTH_WPA2; } else if (wpa_version == IW_AUTH_WPA_VERSION_WPA) { - if (wrq->value == 0){ + if (wrq->value == 0) { pMgmt->eAuthenMode = WMAC_AUTH_WPANONE; } else if (wrq->value == IW_AUTH_KEY_MGMT_PSK) pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK; @@ -1558,17 +1558,17 @@ int iwctl_siwgenie(struct net_device *dev, struct iw_request_info *info, if (pMgmt == NULL) return -EFAULT; - if (wrq->length){ + if (wrq->length) { if ((wrq->length < 2) || (extra[1] + 2 != wrq->length)) { ret = -EINVAL; goto out; } - if (wrq->length > MAX_WPA_IE_LEN){ + if (wrq->length > MAX_WPA_IE_LEN) { ret = -ENOMEM; goto out; } memset(pMgmt->abyWPAIE, 0, MAX_WPA_IE_LEN); - if (copy_from_user(pMgmt->abyWPAIE, extra, wrq->length)){ + if (copy_from_user(pMgmt->abyWPAIE, extra, wrq->length)) { ret = -EFAULT; goto out; } @@ -1615,7 +1615,7 @@ int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info, struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; struct iw_point *wrq = &wrqu->encoding; struct iw_encode_ext *ext = (struct iw_encode_ext*)extra; - struct viawget_wpa_param *param=NULL; + struct viawget_wpa_param *param = NULL; // original member wpa_alg alg_name; u8 addr[6]; @@ -1658,8 +1658,8 @@ int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info, alg_name = WPA_ALG_CCMP; break; default: - PRINT_K("Unknown alg = %d\n",ext->alg); - ret= -ENOMEM; + PRINT_K("Unknown alg = %d\n", ext->alg); + ret = -ENOMEM; goto error; } // recover addr @@ -1671,7 +1671,7 @@ int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info, set_tx = 1; // recover seq,seq_len if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { - seq_len=IW_ENCODE_SEQ_MAX_SIZE; + seq_len = IW_ENCODE_SEQ_MAX_SIZE; memcpy(seq, ext->rx_seq, seq_len); } // recover key,key_len @@ -1702,7 +1702,7 @@ int iwctl_siwencodeext(struct net_device *dev, struct iw_request_info *info, /****set if current action is Network Manager count?? */ /****this method is so foolish,but there is no other way??? */ if (param->u.wpa_key.alg_name == WPA_ALG_NONE) { - if (param->u.wpa_key.key_index ==0) { + if (param->u.wpa_key.key_index == 0) { pDevice->bwextstep0 = true; } if ((pDevice->bwextstep0 == true) && (param->u.wpa_key.key_index == 1)) { @@ -1761,7 +1761,7 @@ int iwctl_siwmlme(struct net_device *dev, struct iw_request_info *info, ret = -EINVAL; return ret; } - switch (mlme->cmd){ + switch (mlme->cmd) { case IW_MLME_DEAUTH: case IW_MLME_DISASSOC: if (pDevice->bLinkPass == true) { @@ -1815,7 +1815,6 @@ static const iw_handler iwctl_handler[] = { IW_HANDLER(SIOCGIWPOWER, iwctl_giwpower), IW_HANDLER(SIOCSIWGENIE, iwctl_siwgenie), IW_HANDLER(SIOCGIWGENIE, iwctl_giwgenie), - IW_HANDLER(SIOCSIWMLME, iwctl_siwmlme), IW_HANDLER(SIOCSIWAUTH, iwctl_siwauth), IW_HANDLER(SIOCGIWAUTH, iwctl_giwauth), IW_HANDLER(SIOCSIWENCODEEXT, iwctl_siwencodeext), diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index e5add185fc7c..5e4a5d0988d7 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -707,6 +707,12 @@ vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id) INIT_WORK(&pDevice->read_work_item, RXvWorkItem); INIT_WORK(&pDevice->rx_mng_work_item, RXvMngWorkItem); + pDevice->pControlURB = usb_alloc_urb(0, GFP_ATOMIC); + if (!pDevice->pControlURB) { + DBG_PRT(MSG_LEVEL_ERR, KERN_ERR"Failed to alloc control urb\n"); + goto err_netdev; + } + pDevice->tx_80211 = device_dma0_tx_80211; pDevice->vnt_mgmt.pAdapter = (void *) pDevice; @@ -853,23 +859,15 @@ static bool device_alloc_bufs(struct vnt_private *pDevice) pRCB++; } - pDevice->pControlURB = usb_alloc_urb(0, GFP_ATOMIC); - if (pDevice->pControlURB == NULL) { - DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc control urb\n"); - goto free_rx_tx; - } - pDevice->pInterruptURB = usb_alloc_urb(0, GFP_ATOMIC); if (pDevice->pInterruptURB == NULL) { DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int urb\n"); - usb_free_urb(pDevice->pControlURB); goto free_rx_tx; } pDevice->intBuf.pDataBuf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL); if (pDevice->intBuf.pDataBuf == NULL) { DBG_PRT(MSG_LEVEL_ERR,KERN_ERR"Failed to alloc int buf\n"); - usb_free_urb(pDevice->pControlURB); usb_free_urb(pDevice->pInterruptURB); goto free_rx_tx; } @@ -1040,9 +1038,7 @@ free_rx_tx: device_free_rx_bufs(pDevice); device_free_tx_bufs(pDevice); device_free_int_bufs(pDevice); - usb_kill_urb(pDevice->pControlURB); usb_kill_urb(pDevice->pInterruptURB); - usb_free_urb(pDevice->pControlURB); usb_free_urb(pDevice->pInterruptURB); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_open fail.. \n"); @@ -1085,8 +1081,6 @@ static int device_close(struct net_device *dev) cancel_delayed_work_sync(&pDevice->run_command_work); cancel_delayed_work_sync(&pDevice->second_callback_work); - del_timer(&pDevice->sTimerTxData); - if (pDevice->bDiversityRegCtlON) { del_timer(&pDevice->TimerSQ3Tmax1); del_timer(&pDevice->TimerSQ3Tmax2); @@ -1113,9 +1107,7 @@ static int device_close(struct net_device *dev) device_free_int_bufs(pDevice); device_free_frag_bufs(pDevice); - usb_kill_urb(pDevice->pControlURB); usb_kill_urb(pDevice->pInterruptURB); - usb_free_urb(pDevice->pControlURB); usb_free_urb(pDevice->pInterruptURB); BSSvClearNodeDBTable(pDevice, 0); @@ -1139,9 +1131,12 @@ static void vt6656_disconnect(struct usb_interface *intf) if (device->dev) { unregister_netdev(device->dev); + + usb_kill_urb(device->pControlURB); + usb_free_urb(device->pControlURB); + free_netdev(device->dev); } - } static int device_dma0_tx_80211(struct sk_buff *skb, struct net_device *dev) diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c index edc8975b2e2a..6334315807bb 100644 --- a/drivers/staging/vt6656/power.c +++ b/drivers/staging/vt6656/power.c @@ -257,10 +257,8 @@ int PSbSendNullPacket(struct vnt_private *pDevice) if (pDevice->bLinkPass == false) return false; - if ((pDevice->bEnablePSMode == false) && - (pDevice->fTxDataInSleep == false)) { - return false; - } + if (pDevice->bEnablePSMode == false && pDevice->tx_trigger == false) + return false; memset(pMgmt->pbyPSPacketPool, 0, sizeof(struct vnt_tx_mgmt) + WLAN_NULLDATA_FR_MAXLEN); diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 93eba18a1b99..35a3ddb41a6a 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -107,8 +107,9 @@ static void s_vGenerateMACHeader(struct vnt_private *pDevice, u8 *pbyBufferAddr, u16 wDuration, struct ethhdr *psEthHeader, int bNeedEncrypt, u16 wFragType, u32 uDMAIdx, u32 uFragIdx); -static void s_vFillTxKey(struct vnt_private *pDevice, u8 *pbyBuf, - u8 *pbyIVHead, PSKeyItem pTransmitKey, u8 *pbyHdrBuf, u16 wPayloadLen, +static void s_vFillTxKey(struct vnt_private *pDevice, + struct vnt_tx_fifo_head *fifo_head, u8 *pbyIVHead, + PSKeyItem pTransmitKey, u8 *pbyHdrBuf, u16 wPayloadLen, struct vnt_mic_hdr *mic_hdr); static void s_vSWencryption(struct vnt_private *pDevice, @@ -179,10 +180,12 @@ static void s_vSaveTxPktInfo(struct vnt_private *pDevice, u8 byPktNum, ETH_ALEN); } -static void s_vFillTxKey(struct vnt_private *pDevice, u8 *pbyBuf, - u8 *pbyIVHead, PSKeyItem pTransmitKey, u8 *pbyHdrBuf, - u16 wPayloadLen, struct vnt_mic_hdr *mic_hdr) +static void s_vFillTxKey(struct vnt_private *pDevice, + struct vnt_tx_fifo_head *fifo_head, u8 *pbyIVHead, + PSKeyItem pTransmitKey, u8 *pbyHdrBuf, u16 wPayloadLen, + struct vnt_mic_hdr *mic_hdr) { + u8 *pbyBuf = (u8 *)&fifo_head->adwTxKey[0]; u32 *pdwIV = (u32 *)pbyIVHead; u32 *pdwExtIV = (u32 *)((u8 *)pbyIVHead + 4); struct ieee80211_hdr *pMACHeader = (struct ieee80211_hdr *)pbyHdrBuf; @@ -427,82 +430,38 @@ static u16 s_uGetRTSCTSDuration(struct vnt_private *pDevice, u8 byDurType, { u32 uCTSTime = 0, uDurTime = 0; - switch (byDurType) { - - case RTSDUR_BB: //RTSDuration_bb - uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); - uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); - break; - - case RTSDUR_BA: //RTSDuration_ba - uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); - uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); - break; - - case RTSDUR_AA: //RTSDuration_aa - uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); - uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); - break; - - case CTSDUR_BA: //CTSDuration_ba - uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck); - break; - - case RTSDUR_BA_F0: //RTSDuration_ba_f0 - uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); - if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { - uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); - } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { - uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); - } - break; - - case RTSDUR_AA_F0: //RTSDuration_aa_f0 - uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); - if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { - uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); - } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { - uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); - } - break; - - case RTSDUR_BA_F1: //RTSDuration_ba_f1 - uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopCCKBasicRate); - if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { - uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); - } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { - uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); - } - break; - - case RTSDUR_AA_F1: //RTSDuration_aa_f1 - uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, 14, pDevice->byTopOFDMBasicRate); - if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { - uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); - } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { - uDurTime = uCTSTime + 2*pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); - } - break; + switch (byDurType) { + case RTSDUR_BB: + case RTSDUR_BA: + case RTSDUR_BA_F0: + case RTSDUR_BA_F1: + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, + 14, pDevice->byTopCCKBasicRate); + uDurTime = uCTSTime + 2 * pDevice->uSIFS + + s_uGetTxRsvTime(pDevice, byPktType, + cbFrameLength, wRate, bNeedAck); + break; - case CTSDUR_BA_F0: //CTSDuration_ba_f0 - if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { - uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE0][wRate-RATE_18M], bNeedAck); - } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { - uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE0][wRate-RATE_18M], bNeedAck); - } - break; + case RTSDUR_AA: + case RTSDUR_AA_F0: + case RTSDUR_AA_F1: + uCTSTime = BBuGetFrameTime(pDevice->byPreambleType, byPktType, + 14, pDevice->byTopOFDMBasicRate); + uDurTime = uCTSTime + 2 * pDevice->uSIFS + + s_uGetTxRsvTime(pDevice, byPktType, + cbFrameLength, wRate, bNeedAck); + break; - case CTSDUR_BA_F1: //CTSDuration_ba_f1 - if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { - uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt0[FB_RATE1][wRate-RATE_18M], bNeedAck); - } else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <=RATE_54M)) { - uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wFB_Opt1[FB_RATE1][wRate-RATE_18M], bNeedAck); - } - break; + case CTSDUR_BA: + case CTSDUR_BA_F0: + case CTSDUR_BA_F1: + uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, + byPktType, cbFrameLength, wRate, bNeedAck); + break; - default: - break; - } + default: + break; + } return cpu_to_le16((u16)uDurTime); } @@ -648,13 +607,13 @@ static u16 vnt_rxtx_rts_g_fb_head(struct vnt_private *priv, buf->wRTSDuration_ba_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_BA_F0, - frame_len, pkt_type, current_rate, need_ack, fb_option); + frame_len, pkt_type, priv->tx_rate_fb0, need_ack, fb_option); buf->wRTSDuration_aa_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F0, - frame_len, pkt_type, current_rate, need_ack, fb_option); + frame_len, pkt_type, priv->tx_rate_fb0, need_ack, fb_option); buf->wRTSDuration_ba_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_BA_F1, - frame_len, pkt_type, current_rate, need_ack, fb_option); + frame_len, pkt_type, priv->tx_rate_fb1, need_ack, fb_option); buf->wRTSDuration_aa_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F1, - frame_len, pkt_type, current_rate, need_ack, fb_option); + frame_len, pkt_type, priv->tx_rate_fb1, need_ack, fb_option); vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration_aa); @@ -695,10 +654,10 @@ static u16 vnt_rxtx_rts_a_fb_head(struct vnt_private *priv, pkt_type, current_rate, need_ack, fb_option); buf->wRTSDuration_f0 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F0, - frame_len, pkt_type, current_rate, need_ack, fb_option); + frame_len, pkt_type, priv->tx_rate_fb0, need_ack, fb_option); buf->wRTSDuration_f1 = s_uGetRTSCTSDuration(priv, RTSDUR_AA_F1, - frame_len, pkt_type, current_rate, need_ack, fb_option); + frame_len, pkt_type, priv->tx_rate_fb1, need_ack, fb_option); vnt_fill_ieee80211_rts(priv, &buf->data, eth_hdr, buf->wDuration); @@ -767,12 +726,12 @@ static u16 s_vFillCTSHead(struct vnt_private *pDevice, u32 uDMAIdx, wCurrentRate, bNeedAck, byFBOption); /* Get CTSDuration_ba_f0 */ pBuf->wCTSDuration_ba_f0 = s_uGetRTSCTSDuration(pDevice, - CTSDUR_BA_F0, cbFrameLength, byPktType, wCurrentRate, - bNeedAck, byFBOption); + CTSDUR_BA_F0, cbFrameLength, byPktType, + pDevice->tx_rate_fb0, bNeedAck, byFBOption); /* Get CTSDuration_ba_f1 */ pBuf->wCTSDuration_ba_f1 = s_uGetRTSCTSDuration(pDevice, - CTSDUR_BA_F1, cbFrameLength, byPktType, wCurrentRate, - bNeedAck, byFBOption); + CTSDUR_BA_F1, cbFrameLength, byPktType, + pDevice->tx_rate_fb1, bNeedAck, byFBOption); /* Get CTS Frame body */ pBuf->data.duration = pBuf->wDuration_ba; pBuf->data.frame_control = TYPE_CTL_CTS; @@ -835,139 +794,147 @@ static u16 s_vGenerateTxParameter(struct vnt_private *pDevice, u16 wFifoCtl; u8 byFBOption = AUTO_FB_NONE; - //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter...\n"); - pFifoHead->wReserved = wCurrentRate; - wFifoCtl = pFifoHead->wFIFOCtl; + pFifoHead->wReserved = wCurrentRate; + wFifoCtl = pFifoHead->wFIFOCtl; - if (wFifoCtl & FIFOCTL_AUTO_FB_0) { - byFBOption = AUTO_FB_0; - } - else if (wFifoCtl & FIFOCTL_AUTO_FB_1) { - byFBOption = AUTO_FB_1; - } + if (wFifoCtl & FIFOCTL_AUTO_FB_0) + byFBOption = AUTO_FB_0; + else if (wFifoCtl & FIFOCTL_AUTO_FB_1) + byFBOption = AUTO_FB_1; if (!pFifoHead) return 0; - if (pDevice->bLongHeader) - cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6; - - if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { - if (need_rts) { - //Fill RsvTime - struct vnt_rrv_time_rts *pBuf = &tx_buffer->tx_head.tx_rts.rts; + if (pDevice->bLongHeader) + cbMACHdLen = WLAN_HDR_ADDR3_LEN + 6; - pBuf->wRTSTxRrvTime_aa = s_uGetRTSCTSRsvTime(pDevice, 2, - byPktType, cbFrameSize, wCurrentRate); - pBuf->wRTSTxRrvTime_ba = s_uGetRTSCTSRsvTime(pDevice, 1, - byPktType, cbFrameSize, wCurrentRate); - pBuf->wRTSTxRrvTime_bb = s_uGetRTSCTSRsvTime(pDevice, 0, + if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) { + if (need_rts) { + struct vnt_rrv_time_rts *pBuf = + &tx_buffer->tx_head.tx_rts.rts; + + pBuf->wRTSTxRrvTime_aa = s_uGetRTSCTSRsvTime(pDevice, 2, + byPktType, cbFrameSize, wCurrentRate); + pBuf->wRTSTxRrvTime_ba = s_uGetRTSCTSRsvTime(pDevice, 1, + byPktType, cbFrameSize, wCurrentRate); + pBuf->wRTSTxRrvTime_bb = s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate); - pBuf->wTxRrvTime_a = vnt_rxtx_rsvtime_le16(pDevice, - byPktType, cbFrameSize, wCurrentRate, bNeedACK); - pBuf->wTxRrvTime_b = vnt_rxtx_rsvtime_le16(pDevice, - PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, - bNeedACK); - if (need_mic) { - *mic_hdr = &tx_buffer->tx_head.tx_rts.tx.mic.hdr; - head = &tx_buffer->tx_head.tx_rts.tx.mic.head; - } else { - head = &tx_buffer->tx_head.tx_rts.tx.head; - } + pBuf->wTxRrvTime_a = vnt_rxtx_rsvtime_le16(pDevice, + byPktType, cbFrameSize, wCurrentRate, bNeedACK); + pBuf->wTxRrvTime_b = vnt_rxtx_rsvtime_le16(pDevice, + PK_TYPE_11B, cbFrameSize, + pDevice->byTopCCKBasicRate, bNeedACK); + + if (need_mic) { + *mic_hdr = &tx_buffer-> + tx_head.tx_rts.tx.mic.hdr; + head = &tx_buffer->tx_head.tx_rts.tx.mic.head; + } else { + head = &tx_buffer->tx_head.tx_rts.tx.head; + } - /* Fill RTS */ - return s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize, - bNeedACK, psEthHeader, wCurrentRate, byFBOption); - } - else {//RTS_needless, PCF mode - //Fill RsvTime - struct vnt_rrv_time_cts *pBuf = &tx_buffer->tx_head.tx_cts.cts; - - pBuf->wTxRrvTime_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, - cbFrameSize, wCurrentRate, bNeedACK); - pBuf->wTxRrvTime_b = vnt_rxtx_rsvtime_le16(pDevice, - PK_TYPE_11B, cbFrameSize, - pDevice->byTopCCKBasicRate, bNeedACK); - pBuf->wCTSTxRrvTime_ba = s_uGetRTSCTSRsvTime(pDevice, 3, - byPktType, cbFrameSize, wCurrentRate); + /* Fill RTS */ + return s_vFillRTSHead(pDevice, byPktType, head, + cbFrameSize, bNeedACK, psEthHeader, + wCurrentRate, byFBOption); + } else { + struct vnt_rrv_time_cts *pBuf = &tx_buffer-> + tx_head.tx_cts.cts; + + pBuf->wTxRrvTime_a = vnt_rxtx_rsvtime_le16(pDevice, + byPktType, cbFrameSize, wCurrentRate, bNeedACK); + pBuf->wTxRrvTime_b = vnt_rxtx_rsvtime_le16(pDevice, + PK_TYPE_11B, cbFrameSize, + pDevice->byTopCCKBasicRate, bNeedACK); + + pBuf->wCTSTxRrvTime_ba = s_uGetRTSCTSRsvTime(pDevice, 3, + byPktType, cbFrameSize, wCurrentRate); + + if (need_mic) { + *mic_hdr = &tx_buffer-> + tx_head.tx_cts.tx.mic.hdr; + head = &tx_buffer->tx_head.tx_cts.tx.mic.head; + } else { + head = &tx_buffer->tx_head.tx_cts.tx.head; + } + + /* Fill CTS */ + return s_vFillCTSHead(pDevice, uDMAIdx, byPktType, + head, cbFrameSize, bNeedACK, wCurrentRate, + byFBOption); + } + } else if (byPktType == PK_TYPE_11A) { if (need_mic) { - *mic_hdr = &tx_buffer->tx_head.tx_cts.tx.mic.hdr; - head = &tx_buffer->tx_head.tx_cts.tx.mic.head; + *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr; + head = &tx_buffer->tx_head.tx_ab.tx.mic.head; } else { - head = &tx_buffer->tx_head.tx_cts.tx.head; + head = &tx_buffer->tx_head.tx_ab.tx.head; } - /* Fill CTS */ - return s_vFillCTSHead(pDevice, uDMAIdx, byPktType, head, - cbFrameSize, bNeedACK, wCurrentRate, byFBOption); - } - } - else if (byPktType == PK_TYPE_11A) { - if (need_mic) { - *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr; - head = &tx_buffer->tx_head.tx_ab.tx.mic.head; - } else { - head = &tx_buffer->tx_head.tx_ab.tx.head; - } - - if (need_rts) { - //Fill RsvTime - struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab; + if (need_rts) { + struct vnt_rrv_time_ab *pBuf = &tx_buffer-> + tx_head.tx_ab.ab; - pBuf->wRTSTxRrvTime = s_uGetRTSCTSRsvTime(pDevice, 2, + pBuf->wRTSTxRrvTime = s_uGetRTSCTSRsvTime(pDevice, 2, byPktType, cbFrameSize, wCurrentRate); - pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, byPktType, - cbFrameSize, wCurrentRate, bNeedACK); - /* Fill RTS */ - return s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize, - bNeedACK, psEthHeader, wCurrentRate, byFBOption); - } else { - //Fill RsvTime - struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab; + pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, + byPktType, cbFrameSize, wCurrentRate, bNeedACK); - pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A, - cbFrameSize, wCurrentRate, bNeedACK); + /* Fill RTS */ + return s_vFillRTSHead(pDevice, byPktType, head, + cbFrameSize, bNeedACK, psEthHeader, + wCurrentRate, byFBOption); + } else { + struct vnt_rrv_time_ab *pBuf = &tx_buffer-> + tx_head.tx_ab.ab; - return vnt_rxtx_datahead_a_fb(pDevice, byPktType, wCurrentRate, - &head->data_head_a_fb, cbFrameSize, bNeedACK); - } - } - else if (byPktType == PK_TYPE_11B) { - if (need_mic) { - *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr; - head = &tx_buffer->tx_head.tx_ab.tx.mic.head; - } else { - head = &tx_buffer->tx_head.tx_ab.tx.head; - } + pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, + PK_TYPE_11A, cbFrameSize, + wCurrentRate, bNeedACK); + + return vnt_rxtx_datahead_a_fb(pDevice, byPktType, + wCurrentRate, &head->data_head_a_fb, + cbFrameSize, bNeedACK); + } + } else if (byPktType == PK_TYPE_11B) { + if (need_mic) { + *mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr; + head = &tx_buffer->tx_head.tx_ab.tx.mic.head; + } else { + head = &tx_buffer->tx_head.tx_ab.tx.head; + } - if (need_rts) { - //Fill RsvTime - struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab; + if (need_rts) { + struct vnt_rrv_time_ab *pBuf = &tx_buffer-> + tx_head.tx_ab.ab; - pBuf->wRTSTxRrvTime = s_uGetRTSCTSRsvTime(pDevice, 0, + pBuf->wRTSTxRrvTime = s_uGetRTSCTSRsvTime(pDevice, 0, byPktType, cbFrameSize, wCurrentRate); - pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, - cbFrameSize, wCurrentRate, bNeedACK); - /* Fill RTS */ - return s_vFillRTSHead(pDevice, byPktType, head, cbFrameSize, + pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, + PK_TYPE_11B, cbFrameSize, wCurrentRate, + bNeedACK); + + /* Fill RTS */ + return s_vFillRTSHead(pDevice, byPktType, head, + cbFrameSize, bNeedACK, psEthHeader, wCurrentRate, byFBOption); - } - else { //RTS_needless, non PCF mode - //Fill RsvTime - struct vnt_rrv_time_ab *pBuf = &tx_buffer->tx_head.tx_ab.ab; + } else { + struct vnt_rrv_time_ab *pBuf = &tx_buffer-> + tx_head.tx_ab.ab; - pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, - cbFrameSize, wCurrentRate, bNeedACK); + pBuf->wTxRrvTime = vnt_rxtx_rsvtime_le16(pDevice, + PK_TYPE_11B, cbFrameSize, + wCurrentRate, bNeedACK); - return vnt_rxtx_datahead_ab(pDevice, byPktType, wCurrentRate, - &head->data_head_ab, cbFrameSize, bNeedACK); - } - } - //DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"s_vGenerateTxParameter END.\n"); + return vnt_rxtx_datahead_ab(pDevice, byPktType, + wCurrentRate, &head->data_head_ab, + cbFrameSize, bNeedACK); + } + } return 0; } @@ -1068,16 +1035,27 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType, pTxBufHead->wFIFOCtl |= FIFOCTL_GRPACK; } - //Set Auto Fallback Ctl - if (wCurrentRate >= RATE_18M) { - if (pDevice->byAutoFBCtrl == AUTO_FB_0) { - pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_0; - byFBOption = AUTO_FB_0; - } else if (pDevice->byAutoFBCtrl == AUTO_FB_1) { - pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_1; - byFBOption = AUTO_FB_1; - } - } + /* Set Auto Fallback Ctl */ + if (wCurrentRate >= RATE_18M) { + if (pDevice->byAutoFBCtrl == AUTO_FB_0) { + pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_0; + + pDevice->tx_rate_fb0 = + wFB_Opt0[FB_RATE0][wCurrentRate - RATE_18M]; + pDevice->tx_rate_fb1 = + wFB_Opt0[FB_RATE1][wCurrentRate - RATE_18M]; + + byFBOption = AUTO_FB_0; + } else if (pDevice->byAutoFBCtrl == AUTO_FB_1) { + pTxBufHead->wFIFOCtl |= FIFOCTL_AUTO_FB_1; + pDevice->tx_rate_fb0 = + wFB_Opt1[FB_RATE0][wCurrentRate - RATE_18M]; + pDevice->tx_rate_fb1 = + wFB_Opt1[FB_RATE1][wCurrentRate - RATE_18M]; + + byFBOption = AUTO_FB_1; + } + } if (bSoftWEP != true) { if ((bNeedEncryption) && (pTransmitKey != NULL)) { //WEP enabled @@ -1196,7 +1174,7 @@ static int s_bPacketToWirelessUsb(struct vnt_private *pDevice, u8 byPktType, if (bNeedEncryption == true) { //Fill TXKEY - s_vFillTxKey(pDevice, (u8 *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, + s_vFillTxKey(pDevice, pTxBufHead, pbyIVHead, pTransmitKey, pbyMacHdr, (u16)cbFrameBodySize, pMICHDR); if (pDevice->bEnableHostWEP) { @@ -1616,7 +1594,7 @@ CMD_STATUS csMgmt_xmit(struct vnt_private *pDevice, } } while(false); //Fill TXKEY - s_vFillTxKey(pDevice, (u8 *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, + s_vFillTxKey(pDevice, pTxBufHead, pbyIVHead, pTransmitKey, (u8 *)pMACHeader, (u16)cbFrameBodySize, NULL); memcpy(pMACHeader, pPacket->p80211Header, cbMacHdLen); @@ -2059,7 +2037,7 @@ void vDMA0_tx_80211(struct vnt_private *pDevice, struct sk_buff *skb) } - s_vFillTxKey(pDevice, (u8 *)(pTxBufHead->adwTxKey), pbyIVHead, pTransmitKey, + s_vFillTxKey(pDevice, pTxBufHead, pbyIVHead, pTransmitKey, pbyMacHdr, (u16)cbFrameBodySize, pMICHDR); if (pDevice->bEnableHostWEP) { diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index 3a03f1d5b685..5fc18ad822d3 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -118,6 +118,9 @@ int PIPEnsControlOut(struct vnt_private *pDevice, u8 byRequest, u16 wValue, if (pDevice->Flags & fMP_CONTROL_READS) return STATUS_FAILURE; + if (pDevice->pControlURB->hcpriv) + return STATUS_FAILURE; + MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES); pDevice->sUsbCtlRequest.bRequestType = 0x40; @@ -177,6 +180,9 @@ int PIPEnsControlIn(struct vnt_private *pDevice, u8 byRequest, u16 wValue, if (pDevice->Flags & fMP_CONTROL_WRITES) return STATUS_FAILURE; + if (pDevice->pControlURB->hcpriv) + return STATUS_FAILURE; + MP_SET_FLAG(pDevice, fMP_CONTROL_READS); pDevice->sUsbCtlRequest.bRequestType = 0xC0; @@ -656,8 +662,6 @@ static void s_nsBulkOutIoCompleteWrite(struct urb *urb) DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Write %d bytes\n",(int)ulBufLen); pDevice->ulBulkOutBytesWrite += ulBufLen; pDevice->ulBulkOutContCRCError = 0; - pDevice->nTxDataTimeCout = 0; - } else { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"BULK Out failed %d\n", status); pDevice->ulBulkOutError++; diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index debb87a6aba7..2f8e2a875331 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -286,6 +286,9 @@ void vRunCommand(struct work_struct *work) u8 byMask[8] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; u8 byData; + if (pDevice->Flags & fMP_DISCONNECTED) + return; + if (pDevice->dwDiagRefCount != 0) return; if (pDevice->bCmdRunning != true) @@ -654,22 +657,6 @@ void vRunCommand(struct work_struct *work) netif_wake_queue(pDevice->dev); } - if(pDevice->IsTxDataTrigger != false) { //TxDataTimer is not triggered at the first time - // printk("Re-initial TxDataTimer****\n"); - del_timer(&pDevice->sTimerTxData); - init_timer(&pDevice->sTimerTxData); - pDevice->sTimerTxData.data = (unsigned long) pDevice; - pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData; - pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback - pDevice->fTxDataInSleep = false; - pDevice->nTxDataTimeCout = 0; - } - else { - // printk("mike:-->First time trigger TimerTxData InSleep\n"); - } - pDevice->IsTxDataTrigger = true; - add_timer(&pDevice->sTimerTxData); - } else if(pMgmt->eCurrState < WMAC_STATE_ASSOCPENDING) { printk("WLAN_ASSOCIATE_WAIT:Association Fail???\n"); @@ -681,7 +668,6 @@ void vRunCommand(struct work_struct *work) vCommandTimerWait((void *) pDevice, ASSOCIATE_TIMEOUT/2); return; } - pDevice->byLinkWaitCount = 0; s_bCommandComplete(pDevice); break; @@ -1159,33 +1145,3 @@ void vResetCommandTimer(struct vnt_private *pDevice) pDevice->bCmdRunning = false; pDevice->bCmdClear = false; } - -void BSSvSecondTxData(struct vnt_private *pDevice) -{ - struct vnt_manager *pMgmt = &pDevice->vnt_mgmt; - - pDevice->nTxDataTimeCout++; - - if (pDevice->nTxDataTimeCout < 4) { //don't tx data if timer less than 40s - // printk("mike:%s-->no data Tx not exceed the desired Time as %d\n",__FUNCTION__, - // (int)pDevice->nTxDataTimeCout); - pDevice->sTimerTxData.expires = RUN_AT(10 * HZ); //10s callback - add_timer(&pDevice->sTimerTxData); - return; - } - - spin_lock_irq(&pDevice->lock); - //is wap_supplicant running successful OR only open && sharekey mode! - if (((pDevice->bLinkPass == true) && - (pMgmt->eAuthenMode < WMAC_AUTH_WPA)) || //open && sharekey linking - (pDevice->fWPA_Authened == true)) { //wpa linking - // printk("mike:%s-->InSleep Tx Data Procedure\n",__FUNCTION__); - pDevice->fTxDataInSleep = true; - PSbSendNullPacket(pDevice); //send null packet - pDevice->fTxDataInSleep = false; - } - spin_unlock_irq(&pDevice->lock); - - pDevice->sTimerTxData.expires = RUN_AT(10 * HZ); //10s callback - add_timer(&pDevice->sTimerTxData); -} diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h index cd12558d5d3f..caf2684ce915 100644 --- a/drivers/staging/vt6656/wcmd.h +++ b/drivers/staging/vt6656/wcmd.h @@ -107,6 +107,4 @@ int bScheduleCommand(struct vnt_private *, CMD_CODE eCommand, u8 *pbyItem0); void vRunCommand(struct work_struct *work); -void BSSvSecondTxData(struct vnt_private *); - #endif /* __WCMD_H__ */ diff --git a/drivers/staging/vt6656/wmgr.c b/drivers/staging/vt6656/wmgr.c index 5a6a5bad0c42..e26c41519b15 100644 --- a/drivers/staging/vt6656/wmgr.c +++ b/drivers/staging/vt6656/wmgr.c @@ -81,7 +81,7 @@ #include "control.h" #include "rndis.h" -static int msglevel =MSG_LEVEL_INFO; +static int msglevel = MSG_LEVEL_INFO; //static int msglevel =MSG_LEVEL_DEBUG; static int ChannelExceedZoneType(struct vnt_private *, u8 byCurrChannel); @@ -213,14 +213,6 @@ void vMgrObjectInit(struct vnt_private *pDevice) pMgmt->wIBSSBeaconPeriod = DEFAULT_IBSS_BI; BSSvClearBSSList((void *) pDevice, false); - init_timer(&pDevice->sTimerTxData); - pDevice->sTimerTxData.data = (unsigned long)pDevice; - pDevice->sTimerTxData.function = (TimerFunction)BSSvSecondTxData; - pDevice->sTimerTxData.expires = RUN_AT(10*HZ); //10s callback - pDevice->fTxDataInSleep = false; - pDevice->IsTxDataTrigger = false; - pDevice->nTxDataTimeCout = 0; - pDevice->cbFreeCmdQueue = CMD_Q_SIZE; pDevice->uCmdDequeueIdx = 0; pDevice->uCmdEnqueueIdx = 0; diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 237479acc3b4..a4fd5c4717a8 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c @@ -98,10 +98,10 @@ static int prism2_domibset_pstr32(wlandevice_t *wlandev, /* The interface functions, called by the cfg80211 layer */ -int prism2_change_virtual_intf(struct wiphy *wiphy, - struct net_device *dev, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) +static int prism2_change_virtual_intf(struct wiphy *wiphy, + struct net_device *dev, + enum nl80211_iftype type, u32 *flags, + struct vif_params *params) { wlandevice_t *wlandev = dev->ml_priv; u32 data; @@ -140,9 +140,9 @@ exit: return err; } -int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, - u8 key_index, bool pairwise, const u8 *mac_addr, - struct key_params *params) +static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, bool pairwise, const u8 *mac_addr, + struct key_params *params) { wlandevice_t *wlandev = dev->ml_priv; u32 did; @@ -199,9 +199,10 @@ exit: return err; } -int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, - u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie, - void (*callback)(void *cookie, struct key_params*)) +static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, bool pairwise, + const u8 *mac_addr, void *cookie, + void (*callback)(void *cookie, struct key_params*)) { wlandevice_t *wlandev = dev->ml_priv; struct key_params params; @@ -228,8 +229,8 @@ int prism2_get_key(struct wiphy *wiphy, struct net_device *dev, return 0; } -int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, - u8 key_index, bool pairwise, const u8 *mac_addr) +static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, bool pairwise, const u8 *mac_addr) { wlandevice_t *wlandev = dev->ml_priv; u32 did; @@ -274,8 +275,8 @@ exit: return err; } -int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev, - u8 key_index, bool unicast, bool multicast) +static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev, + u8 key_index, bool unicast, bool multicast) { wlandevice_t *wlandev = dev->ml_priv; @@ -293,8 +294,8 @@ int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev, } -int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, - u8 *mac, struct station_info *sinfo) +static int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac, struct station_info *sinfo) { wlandevice_t *wlandev = dev->ml_priv; struct p80211msg_lnxreq_commsquality quality; @@ -327,7 +328,7 @@ int prism2_get_station(struct wiphy *wiphy, struct net_device *dev, return result; } -int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +static int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { struct net_device *dev; struct prism2_wiphy_private *priv = wiphy_priv(wiphy); @@ -436,7 +437,7 @@ exit: return err; } -int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed) +static int prism2_set_wiphy_params(struct wiphy *wiphy, u32 changed) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); wlandevice_t *wlandev = priv->wlandev; @@ -478,8 +479,8 @@ exit: return err; } -int prism2_connect(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_connect_params *sme) +static int prism2_connect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) { wlandevice_t *wlandev = dev->ml_priv; struct ieee80211_channel *channel = sme->channel; @@ -602,8 +603,8 @@ exit: return err; } -int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev, - u16 reason_code) +static int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev, + u16 reason_code) { wlandevice_t *wlandev = dev->ml_priv; struct p80211msg_lnxreq_autojoin msg_join; @@ -626,20 +627,20 @@ int prism2_disconnect(struct wiphy *wiphy, struct net_device *dev, } -int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ibss_params *params) +static int prism2_join_ibss(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_ibss_params *params) { return -EOPNOTSUPP; } -int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +static int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev) { return -EOPNOTSUPP; } -int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, - enum nl80211_tx_power_setting type, int mbm) +static int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); wlandevice_t *wlandev = priv->wlandev; @@ -665,8 +666,8 @@ exit: return err; } -int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, - int *dbm) +static int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, + int *dbm) { struct prism2_wiphy_private *priv = wiphy_priv(wiphy); wlandevice_t *wlandev = priv->wlandev; diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h index 2fecca2302f4..2e0bd24f997c 100644 --- a/drivers/staging/wlan-ng/p80211netdev.h +++ b/drivers/staging/wlan-ng/p80211netdev.h @@ -138,7 +138,7 @@ typedef struct p80211_frmrx_t { } 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 */ extern struct iw_handler_def p80211wext_handler_def; int p80211wext_event_associated(struct wlandevice *wlandev, int assoc); diff --git a/drivers/staging/wlan-ng/p80211wep.c b/drivers/staging/wlan-ng/p80211wep.c index 77e50a4aa7e9..c4fabadf5d74 100644 --- a/drivers/staging/wlan-ng/p80211wep.c +++ b/drivers/staging/wlan-ng/p80211wep.c @@ -134,7 +134,7 @@ int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen) return -1; #ifdef WEP_DEBUG - printk(KERN_DEBUG "WEP key %d len %d = %*phC\n", keynum, keylen, + pr_debug("WEP key %d len %d = %*phC\n", keynum, keylen, 8, key); #endif @@ -182,7 +182,7 @@ int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override, keylen += 3; /* add in IV bytes */ #ifdef WEP_DEBUG - printk(KERN_DEBUG "D %d: %*ph (%d %d) %*phC\n", len, 3, key, + pr_debug("D %d: %*ph (%d %d) %*phC\n", len, 3, key, keyidx, keylen, 5, key + 3); #endif @@ -259,7 +259,7 @@ int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum, keylen += 3; /* add in IV bytes */ #ifdef WEP_DEBUG - printk(KERN_DEBUG "E %d (%d/%d %d) %*ph %*phC\n", len, + pr_debug("E %d (%d/%d %d) %*ph %*phC\n", len, iv[3], keynum, keylen, 3, key, 5, key + 3); #endif diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 46dea3f10888..eed58f9a0ad5 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -5274,9 +5274,8 @@ void XGI_SenseCRT1(struct vb_device_info *pVBInfo) outb(0x00, pVBInfo->P3c8); - for (i = 0; i < 256 * 3; i++) { + for (i = 0; i < 256 * 3; i++) outb(0x0F, (pVBInfo->P3c8 + 1)); /* DAC_TEST_PARMS */ - } mdelay(1); @@ -5291,9 +5290,8 @@ void XGI_SenseCRT1(struct vb_device_info *pVBInfo) /* avoid display something, set BLACK DAC if not restore DAC */ outb(0x00, pVBInfo->P3c8); - for (i = 0; i < 256 * 3; i++) { + for (i = 0; i < 256 * 3; i++) outb(0, (pVBInfo->P3c8 + 1)); - } xgifb_reg_set(pVBInfo->P3c4, 0x01, SR01); xgifb_reg_set(pVBInfo->P3d4, 0x63, CR63); diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h index 7168eedbd96a..f17e5b9bd333 100644 --- a/drivers/staging/xgifb/vb_table.h +++ b/drivers/staging/xgifb/vb_table.h @@ -1284,7 +1284,7 @@ static const struct SiS_LVDSData XGI_LVDS1024x768Des_1[] = { {0, 1048, 0, 771}, /* 04 (640x480x60Hz) */ {0, 1048, 0, 771}, /* 05 (800x600x60Hz) */ {0, 1048, 805, 770} /* 06 (1024x768x60Hz) */ -} ; +}; static const struct SiS_LVDSData XGI_LVDS1024x768Des_2[] = { {1142, 856, 622, 587}, /* 00 (320x200,320x400,640x200,640x400) */ diff --git a/drivers/staging/xillybus/xillybus_of.c b/drivers/staging/xillybus/xillybus_of.c index 92c2931f4348..2ae045e332d4 100644 --- a/drivers/staging/xillybus/xillybus_of.c +++ b/drivers/staging/xillybus/xillybus_of.c @@ -198,15 +198,4 @@ static struct platform_driver xillybus_platform_driver = { }, }; -static int __init xillybus_of_init(void) -{ - return platform_driver_register(&xillybus_platform_driver); -} - -static void __exit xillybus_of_exit(void) -{ - platform_driver_unregister(&xillybus_platform_driver); -} - -module_init(xillybus_of_init); -module_exit(xillybus_of_exit); +module_platform_driver(xillybus_platform_driver); diff --git a/drivers/staging/zsmalloc/Kconfig b/drivers/staging/zsmalloc/Kconfig index 7fab032298f3..0ae13cd0908e 100644 --- a/drivers/staging/zsmalloc/Kconfig +++ b/drivers/staging/zsmalloc/Kconfig @@ -1,5 +1,6 @@ config ZSMALLOC bool "Memory allocator for compressed pages" + depends on MMU default n help zsmalloc is a slab-based memory allocator designed to store |