--- /dev/null
+* Freescale i.MX28 LRADC device driver
+
+Required properties:
+- compatible: Should be "fsl,imx28-lradc"
+- reg: Address and length of the register set for the device
+- interrupts: Should contain the LRADC interrupts
+
+Examples:
+
+ lradc@80050000 {
+ compatible = "fsl,imx28-lradc";
+ reg = <0x80050000 0x2000>;
+ interrupts = <10 14 15 16 17 18 19
+ 20 21 22 23 24 25>;
+ };
goto error_free_device;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "No resource defined\n");
- ret = -ENXIO;
- goto error_ret;
- }
-
platform_set_drvdata(pdev, idev);
idev->dev.parent = &pdev->dev;
goto error_free_device;
}
- if (!request_mem_region(res->start, resource_size(res),
- "AT91 adc registers")) {
- dev_err(&pdev->dev, "Resources are unavailable.\n");
- ret = -EBUSY;
- goto error_free_device;
- }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- st->reg_base = ioremap(res->start, resource_size(res));
+ st->reg_base = devm_request_and_ioremap(&pdev->dev, res);
if (!st->reg_base) {
- dev_err(&pdev->dev, "Failed to map registers.\n");
ret = -ENOMEM;
- goto error_release_mem;
+ goto error_free_device;
}
/*
idev);
if (ret) {
dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
- goto error_unmap_reg;
+ goto error_free_device;
}
- st->clk = clk_get(&pdev->dev, "adc_clk");
+ st->clk = devm_clk_get(&pdev->dev, "adc_clk");
if (IS_ERR(st->clk)) {
dev_err(&pdev->dev, "Failed to get the clock.\n");
ret = PTR_ERR(st->clk);
ret = clk_prepare(st->clk);
if (ret) {
dev_err(&pdev->dev, "Could not prepare the clock.\n");
- goto error_free_clk;
+ goto error_free_irq;
}
ret = clk_enable(st->clk);
goto error_unprepare_clk;
}
- st->adc_clk = clk_get(&pdev->dev, "adc_op_clk");
+ st->adc_clk = devm_clk_get(&pdev->dev, "adc_op_clk");
if (IS_ERR(st->adc_clk)) {
dev_err(&pdev->dev, "Failed to get the ADC clock.\n");
ret = PTR_ERR(st->clk);
ret = clk_prepare(st->adc_clk);
if (ret) {
dev_err(&pdev->dev, "Could not prepare the ADC clock.\n");
- goto error_free_adc_clk;
+ goto error_disable_clk;
}
ret = clk_enable(st->adc_clk);
clk_disable(st->adc_clk);
error_unprepare_adc_clk:
clk_unprepare(st->adc_clk);
-error_free_adc_clk:
- clk_put(st->adc_clk);
error_disable_clk:
clk_disable(st->clk);
error_unprepare_clk:
clk_unprepare(st->clk);
-error_free_clk:
- clk_put(st->clk);
error_free_irq:
free_irq(st->irq, idev);
-error_unmap_reg:
- iounmap(st->reg_base);
-error_release_mem:
- release_mem_region(res->start, resource_size(res));
error_free_device:
iio_device_free(idev);
error_ret:
static int __devexit at91_adc_remove(struct platform_device *pdev)
{
struct iio_dev *idev = platform_get_drvdata(pdev);
- struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct at91_adc_state *st = iio_priv(idev);
iio_device_unregister(idev);
at91_adc_trigger_remove(idev);
at91_adc_buffer_remove(idev);
clk_disable_unprepare(st->adc_clk);
- clk_put(st->adc_clk);
clk_disable(st->clk);
clk_unprepare(st->clk);
- clk_put(st->clk);
free_irq(st->irq, idev);
- iounmap(st->reg_base);
- release_mem_region(res->start, resource_size(res));
iio_device_free(idev);
return 0;
/* mm/ashmem.c
-**
-** Anonymous Shared Memory Subsystem, ashmem
-**
-** Copyright (C) 2008 Google, Inc.
-**
-** Robert Love <rlove@google.com>
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** 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.
-*/
+ *
+ * Anonymous Shared Memory Subsystem, ashmem
+ *
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * Robert Love <rlove@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
#define pr_fmt(fmt) "ashmem: " fmt
/*
* copied from get_unused_fd_flags
*/
-int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
+static int task_get_unused_fd_flags(struct binder_proc *proc, int flags)
{
struct files_struct *files = proc->files;
int fd, error;
else
__clear_close_on_exec(fd, fdt);
files->next_fd = fd + 1;
-#if 1
+
/* Sanity check */
if (fdt->fd[fd] != NULL) {
pr_warn("get_unused_fd: slot %d not NULL!\n", fd);
fdt->fd[fd] = NULL;
}
-#endif
+
error = fd;
out:
#include <asm/ioctls.h>
-/*
+/**
* struct logger_log - represents a specific log, such as 'main' or 'radio'
+ * @buffer: The actual ring buffer
+ * @misc: The "misc" device representing the log
+ * @wq: The wait queue for @readers
+ * @readers: This log's readers
+ * @mutex: The mutex that protects the @buffer
+ * @w_off: The current write head offset
+ * @head: The head, or location that readers start reading at.
+ * @size: The size of the log
+ * @logs: The list of log channels
*
* This structure lives from module insertion until module removal, so it does
* not need additional reference counting. The structure is protected by the
* mutex 'mutex'.
*/
struct logger_log {
- unsigned char *buffer;/* the ring buffer itself */
- struct miscdevice misc; /* misc device representing the log */
- wait_queue_head_t wq; /* wait queue for readers */
- struct list_head readers; /* this log's readers */
- struct mutex mutex; /* mutex protecting buffer */
- size_t w_off; /* current write head offset */
- size_t head; /* new readers start here */
- size_t size; /* size of the log */
- struct list_head logs; /* list of log channels (myself)*/
+ unsigned char *buffer;
+ struct miscdevice misc;
+ wait_queue_head_t wq;
+ struct list_head readers;
+ struct mutex mutex;
+ size_t w_off;
+ size_t head;
+ size_t size;
+ struct list_head logs;
};
static LIST_HEAD(log_list);
-/*
+/**
* struct logger_reader - a logging device open for reading
+ * @log: The associated log
+ * @list: The associated entry in @logger_log's list
+ * @r_off: The current read head offset.
*
* This object lives from open to release, so we don't need additional
* reference counting. The structure is protected by log->mutex.
*/
struct logger_reader {
- struct logger_log *log; /* associated log */
- struct list_head list; /* entry in logger_log's list */
- size_t r_off; /* current read head offset */
+ struct logger_log *log;
+ struct list_head list;
+ size_t r_off;
};
/* logger_offset - returns index 'n' into the log via (optimized) modulus */
#include <linux/types.h>
#include <linux/ioctl.h>
+/**
+ * struct logger_entry - defines a single entry that is given to a logger
+ * @len: The length of the payload
+ * @__pad: Two bytes of padding that appear to be required
+ * @pid: The generating process' process ID
+ * @tid: The generating process' thread ID
+ * @sec: The number of seconds that have elapsed since the Epoch
+ * @nsec: The number of nanoseconds that have elapsed since @sec
+ * @msg: The message that is to be logged
+ */
struct logger_entry {
- __u16 len; /* length of the payload */
- __u16 __pad; /* no matter what, we get 2 bytes of padding */
- __s32 pid; /* generating process's pid */
- __s32 tid; /* generating process's tid */
- __s32 sec; /* seconds since Epoch */
- __s32 nsec; /* nanoseconds */
- char msg[0]; /* the entry's payload */
+ __u16 len;
+ __u16 __pad;
+ __s32 pid;
+ __s32 tid;
+ __s32 sec;
+ __s32 nsec;
+ char msg[0];
};
#define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */
},
};
-static int __init timed_gpio_init(void)
-{
- return platform_driver_register(&timed_gpio_driver);
-}
-
-static void __exit timed_gpio_exit(void)
-{
- platform_driver_unregister(&timed_gpio_driver);
-}
-
-module_init(timed_gpio_init);
-module_exit(timed_gpio_exit);
+module_platform_driver(timed_gpio_driver);
MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
MODULE_DESCRIPTION("timed gpio driver");
#define ASUS_OLED_NAME "asus-oled"
#define ASUS_OLED_UNDERSCORE_NAME "asus_oled"
-#define ASUS_OLED_ERROR "Asus OLED Display Error: "
-
#define ASUS_OLED_STATIC 's'
#define ASUS_OLED_ROLL 'r'
#define ASUS_OLED_FLASH 'f'
#define USB_DEVICE_ID_ASUS_LCM2 0x175b
MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com");
-MODULE_DESCRIPTION("Asus OLED Driver v" ASUS_OLED_VERSION);
+MODULE_DESCRIPTION("Asus OLED Driver");
MODULE_LICENSE("GPL");
+MODULE_VERSION(ASUS_OLED_VERSION);
static struct class *oled_class;
static int oled_num;
default:
i = 0;
- printk(ASUS_OLED_ERROR "Unknown OLED Pack Mode: %d!\n",
+ dev_err(odev->dev, "Unknown OLED Pack Mode: %d!\n",
odev->pack_mode);
break;
}
if (i >= odev->buf_size) {
- printk(ASUS_OLED_ERROR "Buffer overflow! Report a bug:"
+ dev_err(odev->dev, "Buffer overflow! Report a bug:"
"offs: %d >= %d i: %d (x: %d y: %d)\n",
(int) odev->buf_offs, (int) odev->buf_size,
(int) i, (int) x, (int) y);
odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
if (odev->buf == NULL) {
odev->buf_size = 0;
- printk(ASUS_OLED_ERROR "Out of memory!\n");
+ dev_err(odev->dev, "Out of memory!\n");
return -ENOMEM;
}
odev->pic_mode = buf[1];
break;
default:
- printk(ASUS_OLED_ERROR "Wrong picture mode: '%c'.\n",
+ dev_err(odev->dev, "Wrong picture mode: '%c'.\n",
buf[1]);
return -EIO;
break;
if (odev->buf == NULL) {
odev->buf_size = 0;
- printk(ASUS_OLED_ERROR "Out of memory!\n");
+ dev_err(odev->dev, "Out of memory!\n");
return -ENOMEM;
}
return count;
error_width:
- printk(ASUS_OLED_ERROR "Wrong picture width specified.\n");
+ dev_err(odev->dev, "Wrong picture width specified.\n");
return -EIO;
error_height:
- printk(ASUS_OLED_ERROR "Wrong picture height specified.\n");
+ dev_err(odev->dev, "Wrong picture height specified.\n");
return -EIO;
error_header:
- printk(ASUS_OLED_ERROR "Wrong picture header.\n");
+ dev_err(odev->dev, "Wrong picture header.\n");
return -EIO;
}
#ifdef VERSION_D5
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLableLength: 0x%X ",
psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength);
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLable[6]: 0x %02X %02X %02X %02X %02X %02X ",
- psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0],
- psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1],
- psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2],
- psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3],
- psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4],
- psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8IPv6FlowLable[6]: 0x%*ph ",
+ 6, psfCSType->cCPacketClassificationRule.
+ u8IPv6FlowLable);
#endif
}
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID: 0x%X", pstAddIndication->sfAdmittedSet.u16CID);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength: 0x%X",
pstAddIndication->sfAdmittedSet.u8ServiceClassNameLength);
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName: 0x %02X %02X %02X %02X %02X %02X",
- pstAddIndication->sfAdmittedSet.u8ServiceClassName[0],
- pstAddIndication->sfAdmittedSet.u8ServiceClassName[1],
- pstAddIndication->sfAdmittedSet.u8ServiceClassName[2],
- pstAddIndication->sfAdmittedSet.u8ServiceClassName[3],
- pstAddIndication->sfAdmittedSet.u8ServiceClassName[4],
- pstAddIndication->sfAdmittedSet.u8ServiceClassName[5]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,
+ "u8ServiceClassName: 0x%*ph",
+ 6, pstAddIndication->sfAdmittedSet.u8ServiceClassName);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService: 0x%02X", pstAddIndication->sfAdmittedSet.u8MBSService);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet: 0x%02X", pstAddIndication->sfAdmittedSet.u8QosParamSet);
psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfServiceLength: 0x%02X",
psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength);
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfService[3]: 0x%02X %02X %02X",
- psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0],
- psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1],
- psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8IPTypeOfService[3]: 0x%*ph",
+ 3, psfCSType->cCPacketClassificationRule.
+ u8IPTypeOfService);
for (uiLoopIndex = 0; uiLoopIndex < 1; uiLoopIndex++)
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Protocol: 0x%02X ", psfCSType->cCPacketClassificationRule.u8Protocol);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRangeLength: 0x%02X ",
psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength);
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRange[4]: 0x %02X %02X %02X %02X ",
- psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[0],
- psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[1],
- psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[2],
- psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[3]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8ProtocolSourcePortRange[4]: "
+ "0x%*ph ", 4, psfCSType->
+ cCPacketClassificationRule.
+ u8ProtocolSourcePortRange);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRangeLength: 0x%02X ",
psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength);
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRange[4]: 0x %02X %02X %02X %02X ",
- psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[0],
- psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[1],
- psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[2],
- psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[3]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8ProtocolDestPortRange[4]: "
+ "0x%*ph ", 4, psfCSType->
+ cCPacketClassificationRule.
+ u8ProtocolDestPortRange);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddressLength: 0x%02X ",
psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength);
u8EthernetSourceMACAddress);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthertypeLength: 0x%02X ", psfCSType->cCPacketClassificationRule.u8EthertypeLength);
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Ethertype[3]: 0x%02X %02X %02X",
- psfCSType->cCPacketClassificationRule.u8Ethertype[0],
- psfCSType->cCPacketClassificationRule.u8Ethertype[1],
- psfCSType->cCPacketClassificationRule.u8Ethertype[2]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8Ethertype[3]: 0x%*ph",
+ 3, psfCSType->cCPacketClassificationRule.
+ u8Ethertype);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UserPriority: 0x%X ", psfCSType->cCPacketClassificationRule.u16UserPriority);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VLANID: 0x%X ", psfCSType->cCPacketClassificationRule.u16VLANID);
#ifdef VERSION_D5
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLableLength: 0x%X ",
psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength);
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLable[6]: 0x %02X %02X %02X %02X %02X %02X ",
- psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0],
- psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1],
- psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2],
- psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3],
- psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4],
- psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL,
+ DBG_LVL_ALL, "u8IPv6FlowLable[6]: 0x%*ph ",
+ 6, psfCSType->cCPacketClassificationRule.
+ u8IPv6FlowLable);
#endif
}
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID: 0x%X", pstAddIndication->sfActiveSet.u32SFID);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID: 0x%X", pstAddIndication->sfActiveSet.u16CID);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength: 0x%X", pstAddIndication->sfActiveSet.u8ServiceClassNameLength);
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName: 0x %02X %02X %02X %02X %02X %02X",
- pstAddIndication->sfActiveSet.u8ServiceClassName[0],
- pstAddIndication->sfActiveSet.u8ServiceClassName[1],
- pstAddIndication->sfActiveSet.u8ServiceClassName[2],
- pstAddIndication->sfActiveSet.u8ServiceClassName[3],
- pstAddIndication->sfActiveSet.u8ServiceClassName[4],
- pstAddIndication->sfActiveSet.u8ServiceClassName[5]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,
+ "u8ServiceClassName: 0x%*ph",
+ 6, pstAddIndication->sfActiveSet.u8ServiceClassName);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService: 0x%02X", pstAddIndication->sfActiveSet.u8MBSService);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet: 0x%02X", pstAddIndication->sfActiveSet.u8QosParamSet);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AuthzSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAuthorizedSet);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ClassifyPrority: %x\n", Adapter->PackInfo[uiLoopIndex].bClassifierPriority);
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxLatency: %x\n", Adapter->PackInfo[uiLoopIndex].uiMaxLatency);
- BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ServiceClassName: %x %x %x %x\n", Adapter->PackInfo[uiLoopIndex].ucServiceClassName[0], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[1], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[2], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[3]);
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO,
+ DBG_LVL_ALL, "ServiceClassName: %*ph\n",
+ 4, Adapter->PackInfo[uiLoopIndex].
+ ucServiceClassName);
/* BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bHeaderSuppressionEnabled :%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled);
* BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalTxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalTxBytes);
* BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalRxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalRxBytes);
BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
Return: STATUS_SUCCESS - If the send was successful.
- Other - If an error occured.
+ Other - If an error occurred.
*/
int PHSTransmit(struct bcm_mini_adapter *Adapter,
- BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successfull");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successful");
return STATUS_SUCCESS;
}
/** 8bit Indicates whether or not MBS service is requested for this Serivce Flow*/
B_UINT8 u8MBSService;
- /** 8bit QOS Parameter Set specifies proper application of QoS paramters to Provisioned, Admitted and Active sets*/
+ /** 8bit QOS Parameter Set specifies proper application of QoS parameters to Provisioned, Admitted and Active sets*/
B_UINT8 u8QosParamSet;
/** 8bit Traffic Priority Of the Service Flow */
BcmGetSectionValStartOffset(Adapter, ISO_IMAGE2_PART3);
}
- /* since this uiSectEndoffset is the size of iso Image. hence for calculating the vitual endoffset
+ /* since this uiSectEndoffset is the size of iso Image. hence for calculating the virtual endoffset
* it should be added in startoffset. so that check done in last of this function can be valued.
*/
uiSectEndOffset = uiSectStartOffset + uiSectEndOffset;
B_UINT32 m_u32PowerSavingModesEnable; //bit 1: 1 Idlemode enable; bit2: 1 Sleepmode Enable
/* PowerSaving Mode Options:
bit 0 = 1: CPE mode - to keep pcmcia if alive;
- bit 1 = 1: CINR reporing in Idlemode Msg
+ bit 1 = 1: CINR reporting in Idlemode Msg
bit 2 = 1: Default PSC Enable in sleepmode*/
B_UINT32 m_u32PowerSavingModeOptions;
struct fsg_common *common;
int err;
- memset(&fsg, 0, sizeof fsg);
+ memset(&fsg, 0, sizeof(fsg));
fsg.nluns = 1;
fsg.luns[0].removable = 1;
fsg.vendor_name = iManufacturer;
To compile this driver as a module, choose M here: the module will be
called adl_pci6208.
-config COMEDI_ADL_PCI7230
- tristate "ADLink PCI-7230 digital io board support"
+config COMEDI_ADL_PCI7X3X
+ tristate "ADLink PCI-723X/743X isolated digital i/o board support"
---help---
- Enable support for ADlink PCI-7230 digital io board support
+ Enable support for ADlink PCI-723X/743X isolated digital i/o boards.
+ Supported boards include the 32-channel PCI-7230 (16 in/16 out),
+ PCI-7233 (32 in), and PCI-7234 (32 out) as well as the 64-channel
+ PCI-7432 (32 in/32 out), PCI-7433 (64 in), and PCI-7434 (64 out).
To compile this driver as a module, choose M here: the module will be
- called adl_pci7230.
+ called adl_pci7x3x.
config COMEDI_ADL_PCI7296
- tristate "ADLink PCI-7296 96 ch. digital io board support"
+ tristate "ADLink PCI-72xx opto-22 compatible digital i/o board support"
select COMEDI_8255
---help---
- Enable support for ADlink PCI-7296 96 ch. digital io board support
+ Enable support for ADlink PCI-72xx opto-22 compatible digital i/o
+ boards. Supported boards include the 24-channel PCI-7224, 48-channel
+ PCI-7248, and 96-channel PCI-7296.
To compile this driver as a module, choose M here: the module will be
called adl_pci7296.
-config COMEDI_ADL_PCI7432
- tristate "ADLink PCI-7432 64 ch. isolated digital io board support"
- ---help---
- Enable support for ADlink PCI-7432 64 ch. isolated digital io board
-
- To compile this driver as a module, choose M here: the module will be
- called adl_pci7432.
-
config COMEDI_ADL_PCI8164
tristate "ADLink PCI-8164 4 Axes Motion Control board support"
---help---
/* by default we allow the insn since we don't have checks for
* all possible cases yet */
default:
- printk(KERN_WARNING
- "comedi: no check for data length of config insn id "
- "%i is implemented.\n"
- " Add a check to %s in %s.\n"
- " Assuming n=%i is correct.\n", data[0], __func__,
- __FILE__, insn->n);
+ pr_warn("comedi: No check for data length of config insn id %i is implemented.\n",
+ data[0]);
+ pr_warn("comedi: Add a check to %s in %s.\n",
+ __func__, __FILE__);
+ pr_warn("comedi: Assuming n=%i is correct.\n", insn->n);
return 0;
- break;
}
return -EINVAL;
}
comedi_reset_async_buf(async);
async->inttrig = NULL;
} else {
- printk(KERN_ERR
- "BUG: (?) do_become_nonbusy called with async=0\n");
+ dev_err(dev->class_dev,
+ "BUG: (?) do_become_nonbusy called with async=NULL\n");
}
s->busy = NULL;
int i;
int retval;
- printk(KERN_INFO "comedi: version " COMEDI_RELEASE
- " - http://www.comedi.org\n");
+ pr_info("comedi: version " COMEDI_RELEASE " - http://www.comedi.org\n");
if (comedi_num_legacy_minors < 0 ||
comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) {
- printk(KERN_ERR "comedi: error: invalid value for module "
- "parameter \"comedi_num_legacy_minors\". Valid values "
- "are 0 through %i.\n", COMEDI_NUM_BOARD_MINORS);
+ pr_err("comedi: error: invalid value for module parameter \"comedi_num_legacy_minors\". Valid values are 0 through %i.\n",
+ COMEDI_NUM_BOARD_MINORS);
return -EINVAL;
}
}
comedi_class = class_create(THIS_MODULE, "comedi");
if (IS_ERR(comedi_class)) {
- printk(KERN_ERR "comedi: failed to create class");
+ pr_err("comedi: failed to create class\n");
cdev_del(&comedi_cdev);
unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
COMEDI_NUM_MINORS);
void comedi_error(const struct comedi_device *dev, const char *s)
{
- printk(KERN_ERR "comedi%d: %s: %s\n", dev->minor,
- dev->driver->driver_name, s);
+ dev_err(dev->class_dev, "%s: %s\n", dev->driver->driver_name, s);
}
EXPORT_SYMBOL(comedi_error);
comedi_device_cleanup(info->device);
kfree(info->device);
kfree(info);
- printk(KERN_ERR
- "comedi: error: "
- "ran out of minor numbers for board device files.\n");
+ pr_err("comedi: error: ran out of minor numbers for board device files.\n");
return -EBUSY;
}
info->device->minor = i;
spin_unlock(&comedi_file_info_table_lock);
if (i == COMEDI_NUM_MINORS) {
kfree(info);
- printk(KERN_ERR
- "comedi: error: "
- "ran out of minor numbers for board device files.\n");
+ pr_err("comedi: error: ran out of minor numbers for board device files.\n");
return -EBUSY;
}
s->minor = i;
#define DPRINTK(format, args...) do { \
if (comedi_debug) \
- printk(KERN_DEBUG "comedi: " format , ## args); \
+ pr_debug("comedi: " format, ## args); \
} while (0)
#define COMEDI_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
if (dev->driver)
dev->driver->detach(dev);
else
- printk(KERN_WARNING
- "BUG: dev->driver=NULL in comedi_device_detach()\n");
+ dev_warn(dev->class_dev,
+ "BUG: dev->driver=NULL in comedi_device_detach()\n");
cleanup_device(dev);
}
return ret;
}
if (!dev->board_name) {
- printk(KERN_WARNING "BUG: dev->board_name=<%p>\n",
- dev->board_name);
+ dev_warn(dev->class_dev, "BUG: dev->board_name=NULL\n");
dev->board_name = "BUG";
}
smp_wmb();
for (driv = comedi_drivers; driv; driv = driv->next) {
if (!try_module_get(driv->module)) {
- printk(KERN_INFO "comedi: failed to increment module count, skipping\n");
continue;
}
if (driv->num_names) {
/* report valid board names before returning error */
for (driv = comedi_drivers; driv; driv = driv->next) {
if (!try_module_get(driv->module)) {
- printk(KERN_INFO
- "comedi: failed to increment module count\n");
continue;
}
comedi_report_boards(driv);
}
return -EIO;
}
+ if (driv->attach == NULL) {
+ /* driver does not support manual configuration */
+ dev_warn(dev->class_dev,
+ "driver '%s' does not support attach using comedi_config\n",
+ driv->driver_name);
+ module_put(driv->module);
+ return -ENOSYS;
+ }
/* initialize dev->driver here so
* comedi_error() can be called from attach */
dev->driver = driv;
mutex_lock(&dev->mutex);
if (dev->attached && dev->driver == driver) {
if (dev->use_count)
- printk(KERN_WARNING "BUG! detaching device with use_count=%d\n",
- dev->use_count);
+ dev_warn(dev->class_dev,
+ "BUG! detaching device with use_count=%d\n",
+ dev->use_count);
comedi_device_detach(dev);
}
mutex_unlock(&dev->mutex);
async =
kzalloc(sizeof(struct comedi_async), GFP_KERNEL);
if (async == NULL) {
- printk(KERN_INFO
- "failed to allocate async struct\n");
+ dev_warn(dev->class_dev,
+ "failed to allocate async struct\n");
return -ENOMEM;
}
init_waitqueue_head(&async->wait_head);
async->prealloc_buf = NULL;
async->prealloc_bufsz = 0;
if (comedi_buf_alloc(dev, s, buf_size) < 0) {
- printk(KERN_INFO "Buffer allocation failed\n");
+ dev_warn(dev->class_dev,
+ "Buffer allocation failed\n");
return -ENOMEM;
}
if (s->buf_change) {
unsigned int i;
const char *const *name_ptr;
- printk(KERN_INFO "comedi: valid board names for %s driver are:\n",
- driv->driver_name);
+ pr_info("comedi: valid board names for %s driver are:\n",
+ driv->driver_name);
name_ptr = driv->board_name;
for (i = 0; i < driv->num_names; i++) {
- printk(KERN_INFO " %s\n", *name_ptr);
+ pr_info(" %s\n", *name_ptr);
name_ptr = (const char **)((char *)name_ptr + driv->offset);
}
if (driv->num_names == 0)
- printk(KERN_INFO " %s\n", driv->driver_name);
+ pr_info(" %s\n", driv->driver_name);
}
static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s)
block_size = num_bytes - count;
if (block_size < 0) {
- printk(KERN_WARNING
- "%s: %s: bug! block_size is negative\n",
- __FILE__, __func__);
+ dev_warn(s->device->class_dev,
+ "%s: %s: bug! block_size is negative\n",
+ __FILE__, __func__);
break;
}
if ((int)(async->munge_ptr + block_size -
{
if ((int)(async->buf_write_count + nbytes -
async->buf_write_alloc_count) > 0) {
- printk(KERN_INFO "comedi: attempted to write-free more bytes than have been write-allocated.\n");
+ dev_info(async->subdevice->device->class_dev,
+ "attempted to write-free more bytes than have been write-allocated.\n");
nbytes = async->buf_write_alloc_count - async->buf_write_count;
}
async->buf_write_count += nbytes;
smp_mb();
if ((int)(async->buf_read_count + nbytes -
async->buf_read_alloc_count) > 0) {
- printk(KERN_INFO
- "comedi: attempted to read-free more bytes than have been read-allocated.\n");
+ dev_info(async->subdevice->device->class_dev,
+ "attempted to read-free more bytes than have been read-allocated.\n");
nbytes = async->buf_read_alloc_count - async->buf_read_count;
}
async->buf_read_count += nbytes;
mutex_lock(&comedi_dev->mutex);
if (comedi_dev->attached)
ret = -EBUSY;
- else if (!try_module_get(driver->module)) {
- printk(KERN_INFO "comedi: failed to increment module count\n");
+ else if (!try_module_get(driver->module))
ret = -EIO;
- } else {
+ else {
/* set comedi_dev->driver here for attach wrapper */
comedi_dev->driver = driver;
ret = (*attach_wrapper)(comedi_dev, context);
* has already been copied to it->board_name */
dev->board_ptr = comedi_recognize(driv, it->board_name);
if (dev->board_ptr == NULL) {
- printk(KERN_WARNING
- "comedi: auto config failed to find board entry"
- " '%s' for driver '%s'\n", it->board_name,
- driv->driver_name);
+ dev_warn(dev->class_dev,
+ "auto config failed to find board entry '%s' for driver '%s'\n",
+ it->board_name, driv->driver_name);
comedi_report_boards(driv);
return -EINVAL;
}
}
+ if (!driv->attach) {
+ dev_warn(dev->class_dev,
+ "BUG! driver '%s' using old-style auto config but has no attach handler\n",
+ driv->driver_name);
+ return -EINVAL;
+ }
return driv->attach(dev, it);
}
obj-$(CONFIG_COMEDI_ADDI_APCI_3501) += addi_apci_3501.o
obj-$(CONFIG_COMEDI_ADDI_APCI_3XXX) += addi_apci_3xxx.o
obj-$(CONFIG_COMEDI_ADL_PCI6208) += adl_pci6208.o
-obj-$(CONFIG_COMEDI_ADL_PCI7230) += adl_pci7230.o
+obj-$(CONFIG_COMEDI_ADL_PCI7X3X) += adl_pci7x3x.o
obj-$(CONFIG_COMEDI_ADL_PCI7296) += adl_pci7296.o
-obj-$(CONFIG_COMEDI_ADL_PCI7432) += adl_pci7432.o
obj-$(CONFIG_COMEDI_ADL_PCI8164) += adl_pci8164.o
obj-$(CONFIG_COMEDI_ADL_PCI9111) += adl_pci9111.o
obj-$(CONFIG_COMEDI_ADL_PCI9118) += adl_pci9118.o
*/
/*
Driver: adl_pci6208
-Description: ADLink PCI-6208A
-Devices: [ADLink] PCI-6208A (adl_pci6208)
+Description: ADLink PCI-6208/6216 Series Multi-channel Analog Output Cards
+Devices: (ADLink) PCI-6208 [adl_pci6208]
+ (ADLink) PCI-6216 [adl_pci6216]
Author: nsyeow <nsyeow@pd.jaring.my>
Updated: Fri, 30 Jan 2004 14:44:27 +0800
Status: untested
-Configuration Options:
- none
+Configuration Options: not applicable, uses PCI auto config
References:
- ni_660x.c
#include "../comedidev.h"
+/*
+ * ADLINK PCI Device ID's supported by this driver
+ */
+#define PCI_DEVICE_ID_PCI6208 0x6208
+#define PCI_DEVICE_ID_PCI6216 0x6216
+
/*
* PCI-6208/6216-GL register map
*/
#define PCI6208_DIO_DI_MASK (0xf0)
#define PCI6208_DIO_DI_SHIFT (4)
-#define PCI6208_MAX_AO_CHANNELS 8
+#define PCI6208_MAX_AO_CHANNELS 16
struct pci6208_board {
const char *name;
static const struct pci6208_board pci6208_boards[] = {
{
- .name = "pci6208a",
- .dev_id = 0x6208,
+ .name = "adl_pci6208",
+ .dev_id = PCI_DEVICE_ID_PCI6208,
.ao_chans = 8,
+ }, {
+ .name = "adl_pci6216",
+ .dev_id = PCI_DEVICE_ID_PCI6216,
+ .ao_chans = 16,
},
};
return insn->n;
}
-static int pci6208_dio_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+static int pci6208_di_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned int val;
+
+ val = inw(dev->iobase + PCI6208_DIO);
+ val = (val & PCI6208_DIO_DI_MASK) >> PCI6208_DIO_DI_SHIFT;
+
+ data[1] = val;
+
+ return insn->n;
+}
+
+static int pci6208_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- unsigned int mask = data[0] & PCI6208_DIO_DO_MASK;
+ unsigned int mask = data[0];
unsigned int bits = data[1];
if (mask) {
s->state &= ~mask;
- s->state |= bits & mask;
+ s->state |= (bits & mask);
outw(s->state, dev->iobase + PCI6208_DIO);
}
- s->state = inw(dev->iobase + PCI6208_DIO);
data[1] = s->state;
return insn->n;
}
-static int pci6208_dio_insn_config(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- int chan = CR_CHAN(insn->chanspec);
- unsigned int mask = 1 << chan;
-
- switch (data[0]) {
- case INSN_CONFIG_DIO_QUERY:
- data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
- break;
- default:
- return -EINVAL;
- }
-
- return insn->n;
-}
-
-static struct pci_dev *pci6208_find_device(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *pci6208_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- const struct pci6208_board *thisboard;
- struct pci_dev *pci_dev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
+ const struct pci6208_board *boardinfo;
int i;
- for_each_pci_dev(pci_dev) {
- if (pci_dev->vendor != PCI_VENDOR_ID_ADLINK)
- continue;
- for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) {
- thisboard = &pci6208_boards[i];
- if (thisboard->dev_id != pci_dev->device)
- continue;
- /* was a particular bus/slot requested? */
- if (bus || slot) {
- /* are we on the wrong bus/slot? */
- if (pci_dev->bus->number != bus ||
- PCI_SLOT(pci_dev->devfn) != slot)
- continue;
- }
- dev_dbg(dev->class_dev,
- "Found %s on bus %d, slot, %d, irq=%d\n",
- thisboard->name,
- pci_dev->bus->number,
- PCI_SLOT(pci_dev->devfn),
- pci_dev->irq);
- dev->board_ptr = thisboard;
- return pci_dev;
- }
+ for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) {
+ boardinfo = &pci6208_boards[i];
+ if (boardinfo->dev_id == pcidev->device)
+ return boardinfo;
}
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
return NULL;
}
-static int pci6208_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int pci6208_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- const struct pci6208_board *thisboard;
+ const struct pci6208_board *boardinfo;
struct pci6208_private *devpriv;
- struct pci_dev *pcidev;
struct comedi_subdevice *s;
+ unsigned int val;
int ret;
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ boardinfo = pci6208_find_boardinfo(dev, pcidev);
+ if (!boardinfo)
+ return -ENODEV;
+ dev->board_ptr = boardinfo;
+ dev->board_name = boardinfo->name;
+
ret = alloc_private(dev, sizeof(*devpriv));
if (ret < 0)
return ret;
devpriv = dev->private;
- pcidev = pci6208_find_device(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
- thisboard = comedi_board(dev);
-
- dev->board_name = thisboard->name;
-
- ret = comedi_pci_enable(pcidev, dev->driver->driver_name);
- if (ret) {
- dev_err(dev->class_dev,
- "Failed to enable PCI device and request regions\n");
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
return ret;
- }
dev->iobase = pci_resource_start(pcidev, 2);
- ret = comedi_alloc_subdevices(dev, 2);
+ ret = comedi_alloc_subdevices(dev, 3);
if (ret)
return ret;
/* analog output subdevice */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
- s->n_chan = thisboard->ao_chans;
+ s->n_chan = boardinfo->ao_chans;
s->maxdata = 0xffff;
s->range_table = &range_bipolar10;
s->insn_write = pci6208_ao_winsn;
s->insn_read = pci6208_ao_rinsn;
s = dev->subdevices + 1;
- /* digital i/o subdevice */
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = 8;
+ /* digital input subdevice */
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 4;
s->maxdata = 1;
s->range_table = &range_digital;
- s->insn_bits = pci6208_dio_insn_bits;
- s->insn_config = pci6208_dio_insn_config;
+ s->insn_bits = pci6208_di_insn_bits;
+ s = dev->subdevices + 2;
+ /* digital output subdevice */
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 4;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pci6208_do_insn_bits;
+
+ /*
+ * Get the read back signals from the digital outputs
+ * and save it as the initial state for the subdevice.
+ */
+ val = inw(dev->iobase + PCI6208_DIO);
+ val = (val & PCI6208_DIO_DO_MASK) >> PCI6208_DIO_DO_SHIFT;
+ s->state = val;
s->io_bits = 0x0f;
- s->state = inw(dev->iobase + PCI6208_DIO);
dev_info(dev->class_dev, "%s: %s, I/O base=0x%04lx\n",
dev->driver->driver_name, dev->board_name, dev->iobase);
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver adl_pci6208_driver = {
.driver_name = "adl_pci6208",
.module = THIS_MODULE,
- .attach = pci6208_attach,
+ .attach_pci = pci6208_attach_pci,
.detach = pci6208_detach,
};
}
static DEFINE_PCI_DEVICE_TABLE(adl_pci6208_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x6208) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6208) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI6216) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, adl_pci6208_pci_table);
+++ /dev/null
-/*
- comedi/drivers/adl_pci7230.c
-
- Hardware comedi driver fot PCI7230 Adlink card
- Copyright (C) 2010 David Fernandez <dfcastelao@gmail.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-/*
-Driver: adl_pci7230
-Description: Driver for the Adlink PCI-7230 32 ch. isolated digital io board
-Devices: [ADLink] PCI-7230 (adl_pci7230)
-Author: David Fernandez <dfcastelao@gmail.com>
-Status: experimental
-Updated: Mon, 14 Apr 2008 15:08:14 +0100
-
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
-*/
-
-#include "../comedidev.h"
-#include <linux/kernel.h>
-
-#define PCI7230_DI 0x00
-#define PCI7230_DO 0x00
-
-#define PCI_DEVICE_ID_PCI7230 0x7230
-
-static int adl_pci7230_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
-
- outl((s->state << 16) & 0xffffffff, dev->iobase + PCI7230_DO);
- }
-
- return insn->n;
-}
-
-static int adl_pci7230_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- data[1] = inl(dev->iobase + PCI7230_DI) & 0xffffffff;
-
- return insn->n;
-}
-
-static struct pci_dev *adl_pci7230_find_pci(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pcidev) {
- if (pcidev->vendor != PCI_VENDOR_ID_ADLINK ||
- pcidev->device != PCI_DEVICE_ID_PCI7230)
- continue;
- if (bus || slot) {
- /* requested particular bus/slot */
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- return pcidev;
- }
- printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
- dev->minor, bus, slot);
- return NULL;
-}
-
-static int adl_pci7230_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct comedi_subdevice *s;
- struct pci_dev *pcidev;
- int ret;
-
- printk(KERN_INFO "comedi%d: adl_pci7230\n", dev->minor);
-
- dev->board_name = "pci7230";
-
- ret = comedi_alloc_subdevices(dev, 2);
- if (ret)
- return ret;
-
- pcidev = adl_pci7230_find_pci(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- if (comedi_pci_enable(pcidev, "adl_pci7230") < 0) {
- printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n",
- dev->minor);
- return -EIO;
- }
- dev->iobase = pci_resource_start(pcidev, 2);
- printk(KERN_DEBUG "comedi: base addr %4lx\n", dev->iobase);
-
- s = dev->subdevices + 0;
- /* Isolated do */
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = 16;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = adl_pci7230_do_insn_bits;
-
- s = dev->subdevices + 1;
- /* Isolated di */
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = 16;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = adl_pci7230_di_insn_bits;
-
- printk(KERN_DEBUG "comedi: attached\n");
-
- return 1;
-}
-
-static void adl_pci7230_detach(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
-}
-
-static struct comedi_driver adl_pci7230_driver = {
- .driver_name = "adl_pci7230",
- .module = THIS_MODULE,
- .attach = adl_pci7230_attach,
- .detach = adl_pci7230_detach,
-};
-
-static int __devinit adl_pci7230_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, &adl_pci7230_driver);
-}
-
-static void __devexit adl_pci7230_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(adl_pci7230_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) },
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, adl_pci7230_pci_table);
-
-static struct pci_driver adl_pci7230_pci_driver = {
- .name = "adl_pci7230",
- .id_table = adl_pci7230_pci_table,
- .probe = adl_pci7230_pci_probe,
- .remove = __devexit_p(adl_pci7230_pci_remove),
-};
-module_comedi_pci_driver(adl_pci7230_driver, adl_pci7230_pci_driver);
-
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
-MODULE_LICENSE("GPL");
/*
- comedi/drivers/adl_pci7296.c
+ * COMEDI driver for the ADLINK PCI-72xx series boards.
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
/*
Driver: adl_pci7296
-Description: Driver for the Adlink PCI-7296 96 ch. digital io board
-Devices: [ADLink] PCI-7296 (adl_pci7296)
+Description: 24/48/96-Channel Opto-22 Compatible Digital I/O Boards
+Devices: (ADLink) PCI-7224 [adl_pci7224] - 24 channels
+ (ADLink) PCI-7248 [adl_pci7248] - 48 channels
+ (ADLink) PCI-7296 [adl_pci7296] - 96 channels
Author: Jon Grierson <jd@renko.co.uk>
Updated: Mon, 14 Apr 2008 15:05:56 +0100
Status: testing
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
+This driver only attaches using the PCI PnP auto config support
+in the comedi core. The module parameter 'comedi_autoconfig'
+must be 1 (default) to enable this feature. The COMEDI_DEVCONFIG
+ioctl, used by the comedi_config utility, is not supported by
+this driver.
+
+These boards also have an 8254 programmable timer/counter chip.
+This chip is not currently supported by this driver.
+
+Interrupt support for these boards is also not currently supported.
+
+Configuration Options: not applicable
*/
#include "../comedidev.h"
-#include <linux/kernel.h>
#include "8255.h"
-/* #include "8253.h" */
-#define PORT1A 0
-#define PORT2A 4
-#define PORT3A 8
-#define PORT4A 12
+/*
+ * PCI Device ID's supported by this driver
+ */
+#define PCI_DEVICE_ID_PCI7224 0x7224
+#define PCI_DEVICE_ID_PCI7248 0x7248
+#define PCI_DEVICE_ID_PCI7296 0x7296
+
+struct adl_pci7296_boardinfo {
+ const char *name;
+ unsigned short device;
+ int nsubdevs;
+};
-#define PCI_DEVICE_ID_PCI7296 0x7296
+static const struct adl_pci7296_boardinfo adl_pci7296_boards[] = {
+ {
+ .name = "adl_pci7224",
+ .device = PCI_DEVICE_ID_PCI7224,
+ .nsubdevs = 1,
+ }, {
+ .name = "adl_pci7248",
+ .device = PCI_DEVICE_ID_PCI7248,
+ .nsubdevs = 2,
+ }, {
+ .name = "adl_pci7296",
+ .device = PCI_DEVICE_ID_PCI7296,
+ .nsubdevs = 4,
+ },
+};
-static struct pci_dev *adl_pci7296_find_pci(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *adl_pci7296_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pcidev) {
- if (pcidev->vendor != PCI_VENDOR_ID_ADLINK ||
- pcidev->device != PCI_DEVICE_ID_PCI7296)
- continue;
- if (bus || slot) {
- /* requested particular bus/slot */
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- return pcidev;
+ const struct adl_pci7296_boardinfo *board;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(adl_pci7296_boards); i++) {
+ board = &adl_pci7296_boards[i];
+ if (pcidev->device == board->device)
+ return board;
}
- printk(KERN_ERR
- "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
- dev->minor, bus, slot);
return NULL;
}
-static int adl_pci7296_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int adl_pci7296_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev;
+ const struct adl_pci7296_boardinfo *board;
struct comedi_subdevice *s;
int ret;
+ int i;
- printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor);
+ comedi_set_hw_dev(dev, &pcidev->dev);
- dev->board_name = "pci7432";
+ board = adl_pci7296_find_boardinfo(dev, pcidev);
+ if (!board)
+ return -ENODEV;
+ dev->board_ptr = board;
+ dev->board_name = board->name;
- ret = comedi_alloc_subdevices(dev, 4);
+ ret = comedi_pci_enable(pcidev, dev->board_name);
if (ret)
return ret;
-
- pcidev = adl_pci7296_find_pci(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- if (comedi_pci_enable(pcidev, "adl_pci7296") < 0) {
- printk(KERN_ERR
- "comedi%d: Failed to enable PCI device and request regions\n",
- dev->minor);
- return -EIO;
- }
-
dev->iobase = pci_resource_start(pcidev, 2);
- printk(KERN_INFO "comedi: base addr %4lx\n", dev->iobase);
-
- /* four 8255 digital io subdevices */
- s = dev->subdevices + 0;
- subdev_8255_init(dev, s, NULL, (unsigned long)(dev->iobase));
- s = dev->subdevices + 1;
- ret = subdev_8255_init(dev, s, NULL,
- (unsigned long)(dev->iobase + PORT2A));
- if (ret < 0)
- return ret;
-
- s = dev->subdevices + 2;
- ret = subdev_8255_init(dev, s, NULL,
- (unsigned long)(dev->iobase + PORT3A));
- if (ret < 0)
+ /*
+ * One, two, or four subdevices are setup by this driver depending
+ * on the number of channels provided by the board. Each subdevice
+ * has 24 channels supported by the 8255 module.
+ */
+ ret = comedi_alloc_subdevices(dev, board->nsubdevs);
+ if (ret)
return ret;
- s = dev->subdevices + 3;
- ret = subdev_8255_init(dev, s, NULL,
- (unsigned long)(dev->iobase + PORT4A));
- if (ret < 0)
- return ret;
+ for (i = 0; i < board->nsubdevs; i++) {
+ s = dev->subdevices + i;
+ ret = subdev_8255_init(dev, s, NULL, dev->iobase + (i * 4));
+ if (ret)
+ return ret;
+ }
- printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", dev->minor);
+ dev_info(dev->class_dev, "%s attached (%d digital i/o channels)\n",
+ dev->board_name, board->nsubdevs * 24);
return 0;
}
static void adl_pci7296_detach(struct comedi_device *dev)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ const struct adl_pci7296_boardinfo *board = comedi_board(dev);
+ struct comedi_subdevice *s;
+ int i;
+ if (dev->subdevices) {
+ for (i = 0; i < board->nsubdevs; i++) {
+ s = dev->subdevices + i;
+ subdev_8255_cleanup(dev, s);
+ }
+ }
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
- if (dev->subdevices) {
- subdev_8255_cleanup(dev, dev->subdevices + 0);
- subdev_8255_cleanup(dev, dev->subdevices + 1);
- subdev_8255_cleanup(dev, dev->subdevices + 2);
- subdev_8255_cleanup(dev, dev->subdevices + 3);
}
}
static struct comedi_driver adl_pci7296_driver = {
.driver_name = "adl_pci7296",
.module = THIS_MODULE,
- .attach = adl_pci7296_attach,
+ .attach_pci = adl_pci7296_attach_pci,
.detach = adl_pci7296_detach,
};
}
static DEFINE_PCI_DEVICE_TABLE(adl_pci7296_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7224) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7248) },
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7296) },
{ 0 }
};
};
module_comedi_pci_driver(adl_pci7296_driver, adl_pci7296_pci_driver);
+MODULE_DESCRIPTION("ADLINK PCI-72xx Opto-22 Compatible Digital I/O Boards");
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
+++ /dev/null
-/*
- comedi/drivers/adl_pci7432.c
-
- Hardware comedi driver fot PCI7432 Adlink card
- Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-/*
-Driver: adl_pci7432
-Description: Driver for the Adlink PCI-7432 64 ch. isolated digital io board
-Devices: [ADLink] PCI-7432 (adl_pci7432)
-Author: Michel Lachaine <mike@mikelachaine.ca>
-Status: experimental
-Updated: Mon, 14 Apr 2008 15:08:14 +0100
-
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
-*/
-
-#include "../comedidev.h"
-#include <linux/kernel.h>
-
-#define PCI7432_DI 0x00
-#define PCI7432_DO 0x00
-
-#define PCI_DEVICE_ID_PCI7432 0x7432
-
-static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- printk(KERN_DEBUG "comedi: pci7432_do_insn_bits called\n");
- printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
-
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= (data[0] & data[1]);
-
- printk(KERN_DEBUG "comedi: out: %8x on iobase %4lx\n", s->state,
- dev->iobase + PCI7432_DO);
- outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO);
- }
- return insn->n;
-}
-
-static int adl_pci7432_di_insn_bits(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
-{
- printk(KERN_DEBUG "comedi: pci7432_di_insn_bits called\n");
- printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
-
- data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff;
- printk(KERN_DEBUG "comedi: data1 %8x\n", data[1]);
-
- return insn->n;
-}
-
-static struct pci_dev *adl_pci7432_find_pci(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pcidev) {
- if (pcidev->vendor != PCI_VENDOR_ID_ADLINK ||
- pcidev->device != PCI_DEVICE_ID_PCI7432)
- continue;
- if (bus || slot) {
- /* requested particular bus/slot */
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- return pcidev;
- }
- printk(KERN_ERR
- "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
- dev->minor, bus, slot);
- return NULL;
-}
-
-static int adl_pci7432_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
- struct comedi_subdevice *s;
- int ret;
-
- printk(KERN_INFO "comedi%d: attach adl_pci7432\n", dev->minor);
-
- dev->board_name = "pci7432";
-
- ret = comedi_alloc_subdevices(dev, 2);
- if (ret)
- return ret;
-
- pcidev = adl_pci7432_find_pci(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- if (comedi_pci_enable(pcidev, "adl_pci7432") < 0) {
- printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n",
- dev->minor);
- return -EIO;
- }
- dev->iobase = pci_resource_start(pcidev, 2);
- printk(KERN_INFO "comedi: base addr %4lx\n", dev->iobase);
-
- s = dev->subdevices + 0;
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = 32;
- s->maxdata = 1;
- s->len_chanlist = 32;
- s->io_bits = 0x00000000;
- s->range_table = &range_digital;
- s->insn_bits = adl_pci7432_di_insn_bits;
-
- s = dev->subdevices + 1;
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = 32;
- s->maxdata = 1;
- s->len_chanlist = 32;
- s->io_bits = 0xffffffff;
- s->range_table = &range_digital;
- s->insn_bits = adl_pci7432_do_insn_bits;
-
- printk(KERN_DEBUG "comedi%d: adl_pci7432 attached\n", dev->minor);
- return 0;
-}
-
-static void adl_pci7432_detach(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
-}
-
-static struct comedi_driver adl_pci7432_driver = {
- .driver_name = "adl_pci7432",
- .module = THIS_MODULE,
- .attach = adl_pci7432_attach,
- .detach = adl_pci7432_detach,
-};
-
-static int __devinit adl_pci7432_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *ent)
-{
- return comedi_pci_auto_config(dev, &adl_pci7432_driver);
-}
-
-static void __devexit adl_pci7432_pci_remove(struct pci_dev *dev)
-{
- comedi_pci_auto_unconfig(dev);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(adl_pci7432_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) },
- { 0 }
-};
-MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table);
-
-static struct pci_driver adl_pci7432_pci_driver = {
- .name = "adl_pci7432",
- .id_table = adl_pci7432_pci_table,
- .probe = adl_pci7432_pci_probe,
- .remove = __devexit_p(adl_pci7432_pci_remove),
-};
-module_comedi_pci_driver(adl_pci7432_driver, adl_pci7432_pci_driver);
-
-MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
-MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ * COMEDI driver for the ADLINK PCI-723x/743x series boards.
+ * Copyright (C) 2012 H Hartley Sweeten <hsweeten@visionengravers.com>
+ *
+ * Based on the adl_pci7230 driver written by:
+ * David Fernandez <dfcastelao@gmail.com>
+ * and the adl_pci7432 driver written by:
+ * Michel Lachaine <mike@mikelachaine.ca>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+Driver: adl_pci7x3x
+Description: 32/64-Channel Isolated Digital I/O Boards
+Devices: (ADLink) PCI-7230 [adl_pci7230] - 16 input / 16 output
+ (ADLink) PCI-7233 [adl_pci7233] - 32 input
+ (ADLink) PCI-7234 [adl_pci7234] - 32 output
+ (ADLink) PCI-7432 [adl_pci7432] - 32 input / 32 output
+ (ADLink) PCI-7433 [adl_pci7433] - 64 input
+ (ADLink) PCI-7434 [adl_pci7434] - 64 output
+Author: H Hartley Sweeten <hsweeten@visionengravers.com>
+Updated: Thu, 02 Aug 2012 14:27:46 -0700
+Status: untested
+
+This driver only attaches using the PCI PnP auto config support
+in the comedi core. The module parameter 'comedi_autoconfig'
+must be 1 (default) to enable this feature. The COMEDI_DEVCONFIG
+ioctl, used by the comedi_config utility, is not supported by
+this driver.
+
+The PCI-7230, PCI-7432 and PCI-7433 boards also support external
+interrupt signals on digital input channels 0 and 1. The PCI-7233
+has dual-interrupt sources for change-of-state (COS) on any 16
+digital input channels of LSB and for COS on any 16 digital input
+lines of MSB. Interrupts are not currently supported by this
+driver.
+
+Configuration Options: not applicable
+*/
+
+#include "../comedidev.h"
+
+/*
+ * PCI Device ID's supported by this driver
+ */
+#define PCI_DEVICE_ID_PCI7230 0x7230
+#define PCI_DEVICE_ID_PCI7233 0x7233
+#define PCI_DEVICE_ID_PCI7234 0x7234
+#define PCI_DEVICE_ID_PCI7432 0x7432
+#define PCI_DEVICE_ID_PCI7433 0x7433
+#define PCI_DEVICE_ID_PCI7434 0x7434
+
+/*
+ * Register I/O map (32-bit access only)
+ */
+#define PCI7X3X_DIO_REG 0x00
+#define PCI743X_DIO_REG 0x04
+
+struct adl_pci7x3x_boardinfo {
+ const char *name;
+ unsigned short device;
+ int nsubdevs;
+ int di_nchan;
+ int do_nchan;
+};
+
+static const struct adl_pci7x3x_boardinfo adl_pci7x3x_boards[] = {
+ {
+ .name = "adl_pci7230",
+ .device = PCI_DEVICE_ID_PCI7230,
+ .nsubdevs = 2,
+ .di_nchan = 16,
+ .do_nchan = 16,
+ }, {
+ .name = "adl_pci7233",
+ .device = PCI_DEVICE_ID_PCI7233,
+ .nsubdevs = 1,
+ .di_nchan = 32,
+ }, {
+ .name = "adl_pci7234",
+ .device = PCI_DEVICE_ID_PCI7234,
+ .nsubdevs = 1,
+ .do_nchan = 32,
+ }, {
+ .name = "adl_pci7432",
+ .device = PCI_DEVICE_ID_PCI7432,
+ .nsubdevs = 2,
+ .di_nchan = 32,
+ .do_nchan = 32,
+ }, {
+ .name = "adl_pci7433",
+ .device = PCI_DEVICE_ID_PCI7433,
+ .nsubdevs = 2,
+ .di_nchan = 64,
+ }, {
+ .name = "adl_pci7434",
+ .device = PCI_DEVICE_ID_PCI7434,
+ .nsubdevs = 2,
+ .do_nchan = 64,
+ }
+};
+
+static int adl_pci7x3x_do_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned long reg = (unsigned long)s->private;
+ unsigned int mask = data[0];
+ unsigned int bits = data[1];
+
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
+
+ outl(s->state, dev->iobase + reg);
+ }
+
+ /*
+ * NOTE: The output register is not readable.
+ * This returned state will not be correct until all the
+ * outputs have been updated.
+ */
+ data[1] = s->state;
+
+ return insn->n;
+}
+
+static int adl_pci7x3x_di_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ unsigned long reg = (unsigned long)s->private;
+
+ data[1] = inl(dev->iobase + reg);
+
+ return insn->n;
+}
+
+static const void *adl_pci7x3x_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct adl_pci7x3x_boardinfo *board;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(adl_pci7x3x_boards); i++) {
+ board = &adl_pci7x3x_boards[i];
+ if (pcidev->device == board->device)
+ return board;
+ }
+ return NULL;
+}
+
+static int adl_pci7x3x_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct adl_pci7x3x_boardinfo *board;
+ struct comedi_subdevice *s;
+ int subdev;
+ int nchan;
+ int ret;
+
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ board = adl_pci7x3x_find_boardinfo(dev, pcidev);
+ if (!board)
+ return -ENODEV;
+ dev->board_ptr = board;
+ dev->board_name = board->name;
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+ dev->iobase = pci_resource_start(pcidev, 2);
+
+ /*
+ * One or two subdevices are setup by this driver depending on
+ * the number of digital inputs and/or outputs provided by the
+ * board. Each subdevice has a maximum of 32 channels.
+ *
+ * PCI-7230 - 2 subdevices: 0 - 16 input, 1 - 16 output
+ * PCI-7233 - 1 subdevice: 0 - 32 input
+ * PCI-7234 - 1 subdevice: 0 - 32 output
+ * PCI-7432 - 2 subdevices: 0 - 32 input, 1 - 32 output
+ * PCI-7433 - 2 subdevices: 0 - 32 input, 1 - 32 input
+ * PCI-7434 - 2 subdevices: 0 - 32 output, 1 - 32 output
+ */
+ ret = comedi_alloc_subdevices(dev, board->nsubdevs);
+ if (ret)
+ return ret;
+
+ subdev = 0;
+
+ if (board->di_nchan) {
+ nchan = min(board->di_nchan, 32);
+
+ s = dev->subdevices + subdev;
+ /* Isolated digital inputs 0 to 15/31 */
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = nchan;
+ s->maxdata = 1;
+ s->insn_bits = adl_pci7x3x_di_insn_bits;
+ s->range_table = &range_digital;
+
+ s->private = (void *)PCI7X3X_DIO_REG;
+
+ subdev++;
+
+ nchan = board->di_nchan - nchan;
+ if (nchan) {
+ s = dev->subdevices + subdev;
+ /* Isolated digital inputs 32 to 63 */
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = nchan;
+ s->maxdata = 1;
+ s->insn_bits = adl_pci7x3x_di_insn_bits;
+ s->range_table = &range_digital;
+
+ s->private = (void *)PCI743X_DIO_REG;
+
+ subdev++;
+ }
+ }
+
+ if (board->do_nchan) {
+ nchan = min(board->do_nchan, 32);
+
+ s = dev->subdevices + subdev;
+ /* Isolated digital outputs 0 to 15/31 */
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = nchan;
+ s->maxdata = 1;
+ s->insn_bits = adl_pci7x3x_do_insn_bits;
+ s->range_table = &range_digital;
+
+ s->private = (void *)PCI7X3X_DIO_REG;
+
+ subdev++;
+
+ nchan = board->do_nchan - nchan;
+ if (nchan) {
+ s = dev->subdevices + subdev;
+ /* Isolated digital outputs 32 to 63 */
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = nchan;
+ s->maxdata = 1;
+ s->insn_bits = adl_pci7x3x_do_insn_bits;
+ s->range_table = &range_digital;
+
+ s->private = (void *)PCI743X_DIO_REG;
+
+ subdev++;
+ }
+ }
+
+ dev_info(dev->class_dev, "%s attached (%d inputs/%d outputs)\n",
+ dev->board_name, board->di_nchan, board->do_nchan);
+
+ return 0;
+}
+
+static void adl_pci7x3x_detach(struct comedi_device *dev)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ }
+}
+
+static struct comedi_driver adl_pci7x3x_driver = {
+ .driver_name = "adl_pci7x3x",
+ .module = THIS_MODULE,
+ .attach_pci = adl_pci7x3x_attach_pci,
+ .detach = adl_pci7x3x_detach,
+};
+
+static int __devinit adl_pci7x3x_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *ent)
+{
+ return comedi_pci_auto_config(dev, &adl_pci7x3x_driver);
+}
+
+static void __devexit adl_pci7x3x_pci_remove(struct pci_dev *dev)
+{
+ comedi_pci_auto_unconfig(dev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(adl_pci7x3x_pci_table) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7233) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7234) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7433) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7434) },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, adl_pci7x3x_pci_table);
+
+static struct pci_driver adl_pci7x3x_pci_driver = {
+ .name = "adl_pci7x3x",
+ .id_table = adl_pci7x3x_pci_table,
+ .probe = adl_pci7x3x_pci_probe,
+ .remove = __devexit_p(adl_pci7x3x_pci_remove),
+};
+module_comedi_pci_driver(adl_pci7x3x_driver, adl_pci7x3x_pci_driver);
+
+MODULE_DESCRIPTION("ADLINK PCI-723x/743x Isolated Digital I/O boards");
+MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
+MODULE_LICENSE("GPL");
Status: experimental
Updated: Mon, 14 Apr 2008 15:10:32 +0100
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
+Configuration Options: not applicable, uses PCI auto config
*/
#include "../comedidev.h"
return 2;
}
-static struct pci_dev *adl_pci8164_find_pci(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int adl_pci8164_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pcidev) {
- if (pcidev->vendor != PCI_VENDOR_ID_ADLINK ||
- pcidev->device != PCI_DEVICE_ID_PCI8164)
- continue;
- if (bus || slot) {
- /* requested particular bus/slot */
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- return pcidev;
- }
- printk(KERN_ERR
- "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
- dev->minor, bus, slot);
- return NULL;
-}
-
-static int adl_pci8164_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
struct comedi_subdevice *s;
int ret;
- printk(KERN_INFO "comedi: attempt to attach...\n");
- printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor);
+ comedi_set_hw_dev(dev, &pcidev->dev);
- dev->board_name = "pci8164";
+ dev->board_name = dev->driver->driver_name;
- ret = comedi_alloc_subdevices(dev, 4);
+ ret = comedi_pci_enable(pcidev, dev->board_name);
if (ret)
return ret;
-
- pcidev = adl_pci8164_find_pci(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- if (comedi_pci_enable(pcidev, "adl_pci8164") < 0) {
- printk(KERN_ERR "comedi%d: Failed to enable "
- "PCI device and request regions\n", dev->minor);
- return -EIO;
- }
dev->iobase = pci_resource_start(pcidev, 2);
- printk(KERN_DEBUG "comedi: base addr %4lx\n", dev->iobase);
+
+ ret = comedi_alloc_subdevices(dev, 4);
+ if (ret)
+ return ret;
s = dev->subdevices + 0;
s->type = COMEDI_SUBD_PROC;
s->insn_read = adl_pci8164_insn_read_buf1;
s->insn_write = adl_pci8164_insn_write_buf1;
- printk(KERN_INFO "comedi: attached\n");
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+
return 0;
}
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver adl_pci8164_driver = {
.driver_name = "adl_pci8164",
.module = THIS_MODULE,
- .attach = adl_pci8164_attach,
+ .attach_pci = adl_pci8164_attach_pci,
.detach = adl_pci8164_detach,
};
* correct channel number on every 12 bit
* sample */
-#undef PCI171X_EXTDEBUG
-
#define DRV_NAME "adv_pci1710"
-#undef DPRINTK
-#ifdef PCI171X_EXTDEBUG
-#define DPRINTK(fmt, args...) printk(fmt, ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
#define PCI_VENDOR_ID_ADVANTECH 0x13fe
/* hardware types of the cards */
};
static const struct boardtype boardtypes[] = {
- {"pci1710", 0x1710,
- IORANGE_171x, 1, TYPE_PCI171X,
- 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff,
- &range_pci1710_3, range_codes_pci1710_3,
- &range_pci171x_da,
- 10000, 2048},
- {"pci1710hg", 0x1710,
- IORANGE_171x, 1, TYPE_PCI171X,
- 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff,
- &range_pci1710hg, range_codes_pci1710hg,
- &range_pci171x_da,
- 10000, 2048},
- {"pci1711", 0x1711,
- IORANGE_171x, 1, TYPE_PCI171X,
- 16, 0, 2, 16, 16, 1, 0x0fff, 0x0fff,
- &range_pci17x1, range_codes_pci17x1, &range_pci171x_da,
- 10000, 512},
- {"pci1713", 0x1713,
- IORANGE_171x, 1, TYPE_PCI1713,
- 32, 16, 0, 0, 0, 0, 0x0fff, 0x0000,
- &range_pci1710_3, range_codes_pci1710_3, NULL,
- 10000, 2048},
- {"pci1720", 0x1720,
- IORANGE_1720, 0, TYPE_PCI1720,
- 0, 0, 4, 0, 0, 0, 0x0000, 0x0fff,
- NULL, NULL, &range_pci1720,
- 0, 0},
- {"pci1731", 0x1731,
- IORANGE_171x, 1, TYPE_PCI171X,
- 16, 0, 0, 16, 16, 0, 0x0fff, 0x0000,
- &range_pci17x1, range_codes_pci17x1, NULL,
- 10000, 512},
- /* dummy entry corresponding to driver name */
- {.name = DRV_NAME},
+ {
+ .name = "pci1710",
+ .device_id = 0x1710,
+ .iorange = IORANGE_171x,
+ .have_irq = 1,
+ .cardtype = TYPE_PCI171X,
+ .n_aichan = 16,
+ .n_aichand = 8,
+ .n_aochan = 2,
+ .n_dichan = 16,
+ .n_dochan = 16,
+ .n_counter = 1,
+ .ai_maxdata = 0x0fff,
+ .ao_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci1710_3,
+ .rangecode_ai = range_codes_pci1710_3,
+ .rangelist_ao = &range_pci171x_da,
+ .ai_ns_min = 10000,
+ .fifo_half_size = 2048,
+ }, {
+ .name = "pci1710hg",
+ .device_id = 0x1710,
+ .iorange = IORANGE_171x,
+ .have_irq = 1,
+ .cardtype = TYPE_PCI171X,
+ .n_aichan = 16,
+ .n_aichand = 8,
+ .n_aochan = 2,
+ .n_dichan = 16,
+ .n_dochan = 16,
+ .n_counter = 1,
+ .ai_maxdata = 0x0fff,
+ .ao_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci1710hg,
+ .rangecode_ai = range_codes_pci1710hg,
+ .rangelist_ao = &range_pci171x_da,
+ .ai_ns_min = 10000,
+ .fifo_half_size = 2048,
+ }, {
+ .name = "pci1711",
+ .device_id = 0x1711,
+ .iorange = IORANGE_171x,
+ .have_irq = 1,
+ .cardtype = TYPE_PCI171X,
+ .n_aichan = 16,
+ .n_aochan = 2,
+ .n_dichan = 16,
+ .n_dochan = 16,
+ .n_counter = 1,
+ .ai_maxdata = 0x0fff,
+ .ao_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci17x1,
+ .rangecode_ai = range_codes_pci17x1,
+ .rangelist_ao = &range_pci171x_da,
+ .ai_ns_min = 10000,
+ .fifo_half_size = 512,
+ }, {
+ .name = "pci1713",
+ .device_id = 0x1713,
+ .iorange = IORANGE_171x,
+ .have_irq = 1,
+ .cardtype = TYPE_PCI1713,
+ .n_aichan = 32,
+ .n_aichand = 16,
+ .ai_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci1710_3,
+ .rangecode_ai = range_codes_pci1710_3,
+ .ai_ns_min = 10000,
+ .fifo_half_size = 2048,
+ }, {
+ .name = "pci1720",
+ .device_id = 0x1720,
+ .iorange = IORANGE_1720,
+ .cardtype = TYPE_PCI1720,
+ .n_aochan = 4,
+ .ao_maxdata = 0x0fff,
+ .rangelist_ao = &range_pci1720,
+ }, {
+ .name = "pci1731",
+ .device_id = 0x1731,
+ .iorange = IORANGE_171x,
+ .have_irq = 1,
+ .cardtype = TYPE_PCI171X,
+ .n_aichan = 16,
+ .n_dichan = 16,
+ .n_dochan = 16,
+ .ai_maxdata = 0x0fff,
+ .rangelist_ai = &range_pci17x1,
+ .rangecode_ai = range_codes_pci17x1,
+ .ai_ns_min = 10000,
+ .fifo_half_size = 512,
+ }, {
+ /* dummy entry corresponding to driver name */
+ .name = DRV_NAME,
+ },
};
struct pci1710_private {
* internal state */
};
-#define devpriv ((struct pci1710_private *)dev->private)
-#define this_board ((const struct boardtype *)dev->board_ptr)
+/* used for gain list programming */
+static const unsigned int muxonechan[] = {
+ 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,
+ 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
+ 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717,
+ 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f
+};
/*
==============================================================================
+ Check if channel list from user is builded correctly
+ If it's ok, then program scan/gain logic.
+ This works for all cards.
*/
-
static int check_channel_list(struct comedi_device *dev,
struct comedi_subdevice *s,
- unsigned int *chanlist, unsigned int n_chan);
+ unsigned int *chanlist, unsigned int n_chan)
+{
+ unsigned int chansegment[32];
+ unsigned int i, nowmustbechan, seglen, segpos;
+
+ /* correct channel and range number check itself comedi/range.c */
+ if (n_chan < 1) {
+ comedi_error(dev, "range/channel list is empty!");
+ return 0;
+ }
+
+ if (n_chan == 1)
+ return 1; /* seglen=1 */
+
+ chansegment[0] = chanlist[0]; /* first channel is every time ok */
+ for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
+ if (chanlist[0] == chanlist[i])
+ break; /* we detected a loop, stop */
+ if ((CR_CHAN(chanlist[i]) & 1) &&
+ (CR_AREF(chanlist[i]) == AREF_DIFF)) {
+ comedi_error(dev, "Odd channel cannot be differential input!\n");
+ return 0;
+ }
+ nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
+ if (CR_AREF(chansegment[i - 1]) == AREF_DIFF)
+ nowmustbechan = (nowmustbechan + 1) % s->n_chan;
+ if (nowmustbechan != CR_CHAN(chanlist[i])) {
+ printk("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
+ i, CR_CHAN(chanlist[i]), nowmustbechan,
+ CR_CHAN(chanlist[0]));
+ return 0;
+ }
+ chansegment[i] = chanlist[i]; /* next correct channel in list */
+ }
+
+ for (i = 0, segpos = 0; i < n_chan; i++) {
+ if (chanlist[i] != chansegment[i % seglen]) {
+ printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
+ i, CR_CHAN(chansegment[i]),
+ CR_RANGE(chansegment[i]),
+ CR_AREF(chansegment[i]),
+ CR_CHAN(chanlist[i % seglen]),
+ CR_RANGE(chanlist[i % seglen]),
+ CR_AREF(chansegment[i % seglen]));
+ return 0;
+ }
+ }
+ return seglen;
+}
+
static void setup_channel_list(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int *chanlist, unsigned int n_chan,
- unsigned int seglen);
-static void start_pacer(struct comedi_device *dev, int mode,
- unsigned int divisor1, unsigned int divisor2);
-static int pci1710_reset(struct comedi_device *dev);
-static int pci171x_ai_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s);
+ unsigned int seglen)
+{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci1710_private *devpriv = dev->private;
+ unsigned int i, range, chanprog;
-/* used for gain list programming */
-static const unsigned int muxonechan[] = {
- 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,
- 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
- 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717,
- 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f
-};
+ devpriv->act_chanlist_len = seglen;
+ devpriv->act_chanlist_pos = 0;
+
+ for (i = 0; i < seglen; i++) { /* store range list to card */
+ chanprog = muxonechan[CR_CHAN(chanlist[i])];
+ outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */
+ range = this_board->rangecode_ai[CR_RANGE(chanlist[i])];
+ if (CR_AREF(chanlist[i]) == AREF_DIFF)
+ range |= 0x0020;
+ outw(range, dev->iobase + PCI171x_RANGE); /* select gain */
+#ifdef PCI171x_PARANOIDCHECK
+ devpriv->act_chanlist[i] =
+ (CR_CHAN(chanlist[i]) << 12) & 0xf000;
+#endif
+ }
+#ifdef PCI171x_PARANOIDCHECK
+ for ( ; i < n_chan; i++) { /* store remainder of channel list */
+ devpriv->act_chanlist[i] =
+ (CR_CHAN(chanlist[i]) << 12) & 0xf000;
+ }
+#endif
+
+ devpriv->ai_et_MuxVal =
+ CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8);
+ /* select channel interval to scan */
+ outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX);
+}
/*
==============================================================================
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci1710_private *devpriv = dev->private;
int n, timeout;
#ifdef PCI171x_PARANOIDCHECK
+ const struct boardtype *this_board = comedi_board(dev);
unsigned int idata;
#endif
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_insn_read_ai(...)\n");
devpriv->CntrlReg &= Control_CNT0;
devpriv->CntrlReg |= Control_SW; /* set software trigger */
outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
setup_channel_list(dev, s, &insn->chanspec, 1, 1);
- DPRINTK("adv_pci1710 A ST=%4x IO=%x\n",
- inw(dev->iobase + PCI171x_STATUS),
- dev->iobase + PCI171x_STATUS);
for (n = 0; n < insn->n; n++) {
outw(0, dev->iobase + PCI171x_SOFTTRG); /* start conversion */
- DPRINTK("adv_pci1710 B n=%d ST=%4x\n", n,
- inw(dev->iobase + PCI171x_STATUS));
/* udelay(1); */
- DPRINTK("adv_pci1710 C n=%d ST=%4x\n", n,
- inw(dev->iobase + PCI171x_STATUS));
timeout = 100;
while (timeout--) {
if (!(inw(dev->iobase + PCI171x_STATUS) & Status_FE))
goto conv_finish;
- if (!(timeout % 10))
- DPRINTK("adv_pci1710 D n=%d tm=%d ST=%4x\n", n,
- timeout,
- inw(dev->iobase + PCI171x_STATUS));
}
comedi_error(dev, "A/D insn timeout");
outb(0, dev->iobase + PCI171x_CLRFIFO);
outb(0, dev->iobase + PCI171x_CLRINT);
data[n] = 0;
- DPRINTK
- ("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n",
- n);
return -ETIME;
conv_finish:
outb(0, dev->iobase + PCI171x_CLRFIFO);
outb(0, dev->iobase + PCI171x_CLRINT);
- DPRINTK("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n", n);
return n;
}
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci1710_private *devpriv = dev->private;
int n, chan, range, ofs;
chan = CR_CHAN(insn->chanspec);
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci1710_private *devpriv = dev->private;
int n, chan;
chan = CR_CHAN(insn->chanspec);
return insn->n;
}
+/*
+==============================================================================
+*/
+static void start_pacer(struct comedi_device *dev, int mode,
+ unsigned int divisor1, unsigned int divisor2)
+{
+ outw(0xb4, dev->iobase + PCI171x_CNTCTRL);
+ outw(0x74, dev->iobase + PCI171x_CNTCTRL);
+
+ if (mode == 1) {
+ outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2);
+ outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2);
+ outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1);
+ outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1);
+ }
+}
+
/*
==============================================================================
*/
struct comedi_insn *insn,
unsigned int *data)
{
+ struct pci1710_private *devpriv = dev->private;
uint msb, lsb, ccntrl, status;
lsb = data[0] & 0x00FF;
{
#ifdef unused
/* This doesn't work like a normal Comedi counter config */
+ struct pci1710_private *devpriv = dev->private;
uint ccntrl = 0;
devpriv->cnt0_write_wait = data[0] & 0x20;
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci1710_private *devpriv = dev->private;
int n, rangereg, chan;
chan = CR_CHAN(insn->chanspec);
return n;
}
+/*
+==============================================================================
+*/
+static int pci171x_ai_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci1710_private *devpriv = dev->private;
+
+ switch (this_board->cardtype) {
+ default:
+ devpriv->CntrlReg &= Control_CNT0;
+ devpriv->CntrlReg |= Control_SW;
+
+ outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */
+ start_pacer(dev, -1, 0, 0);
+ outb(0, dev->iobase + PCI171x_CLRFIFO);
+ outb(0, dev->iobase + PCI171x_CLRINT);
+ break;
+ }
+
+ devpriv->ai_do = 0;
+ devpriv->ai_act_scan = 0;
+ s->async->cur_chan = 0;
+ devpriv->ai_buf_ptr = 0;
+ devpriv->neverending_ai = 0;
+
+ return 0;
+}
+
/*
==============================================================================
*/
static void interrupt_pci1710_every_sample(void *d)
{
struct comedi_device *dev = d;
+ struct pci1710_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->subdevices + 0;
int m;
#ifdef PCI171x_PARANOIDCHECK
+ const struct boardtype *this_board = comedi_board(dev);
short sampl;
#endif
- DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_every_sample(...)\n");
m = inw(dev->iobase + PCI171x_STATUS);
if (m & Status_FE) {
printk("comedi%d: A/D FIFO empty (%4x)\n", dev->minor, m);
outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */
- DPRINTK("FOR ");
for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) {
#ifdef PCI171x_PARANOIDCHECK
sampl = inw(dev->iobase + PCI171x_AD_DATA);
- DPRINTK("%04x:", sampl);
if (this_board->cardtype != TYPE_PCI1713)
if ((sampl & 0xf000) !=
devpriv->act_chanlist[s->async->cur_chan]) {
comedi_event(dev, s);
return;
}
- DPRINTK("%8d %2d %8d~", s->async->buf_int_ptr,
- s->async->cur_chan, s->async->buf_int_count);
comedi_buf_put(s->async, sampl & 0x0fff);
#else
comedi_buf_put(s->async,
if (s->async->cur_chan == 0) { /* one scan done */
devpriv->ai_act_scan++;
- DPRINTK
- ("adv_pci1710 EDBG: EOS1 bic %d bip %d buc %d bup %d\n",
- s->async->buf_int_count, s->async->buf_int_ptr,
- s->async->buf_user_count, s->async->buf_user_ptr);
- DPRINTK("adv_pci1710 EDBG: EOS2\n");
if ((!devpriv->neverending_ai) &&
(devpriv->ai_act_scan >= devpriv->ai_scans)) {
/* all data sampled */
}
outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */
- DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_every_sample(...)\n");
comedi_event(dev, s);
}
static int move_block_from_fifo(struct comedi_device *dev,
struct comedi_subdevice *s, int n, int turn)
{
+ struct pci1710_private *devpriv = dev->private;
int i, j;
#ifdef PCI171x_PARANOIDCHECK
+ const struct boardtype *this_board = comedi_board(dev);
int sampl;
#endif
- DPRINTK("adv_pci1710 EDBG: BGN: move_block_from_fifo(...,%d,%d)\n", n,
- turn);
+
j = s->async->cur_chan;
for (i = 0; i < n; i++) {
#ifdef PCI171x_PARANOIDCHECK
}
}
s->async->cur_chan = j;
- DPRINTK("adv_pci1710 EDBG: END: move_block_from_fifo(...)\n");
return 0;
}
static void interrupt_pci1710_half_fifo(void *d)
{
struct comedi_device *dev = d;
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci1710_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->subdevices + 0;
int m, samplesinbuf;
- DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_half_fifo(...)\n");
m = inw(dev->iobase + PCI171x_STATUS);
if (!(m & Status_FH)) {
printk("comedi%d: A/D FIFO not half full! (%4x)\n",
return;
}
outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */
- DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_half_fifo(...)\n");
comedi_event(dev, s);
}
static irqreturn_t interrupt_service_pci1710(int irq, void *d)
{
struct comedi_device *dev = d;
+ struct pci1710_private *devpriv = dev->private;
- DPRINTK("adv_pci1710 EDBG: BGN: interrupt_service_pci1710(%d,...)\n",
- irq);
if (!dev->attached) /* is device attached? */
return IRQ_NONE; /* no, exit */
/* is this interrupt from our board? */
if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ))
return IRQ_NONE; /* no, exit */
- DPRINTK("adv_pci1710 EDBG: interrupt_service_pci1710() ST: %4x\n",
- inw(dev->iobase + PCI171x_STATUS));
-
if (devpriv->ai_et) { /* Switch from initial TRIG_EXT to TRIG_xxx. */
devpriv->ai_et = 0;
devpriv->CntrlReg &= Control_CNT0;
} else {
interrupt_pci1710_half_fifo(d);
}
- DPRINTK("adv_pci1710 EDBG: END: interrupt_service_pci1710(...)\n");
return IRQ_HANDLED;
}
static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev,
struct comedi_subdevice *s)
{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci1710_private *devpriv = dev->private;
unsigned int divisor1 = 0, divisor2 = 0;
unsigned int seglen;
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_docmd_and_mode(%d,...)\n",
- mode);
start_pacer(dev, -1, 0, 0); /* stop pacer */
seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
&divisor2, &devpriv->ai_timer1,
devpriv->ai_flags & TRIG_ROUND_MASK);
- DPRINTK
- ("adv_pci1710 EDBG: OSC base=%u div1=%u div2=%u timer=%u\n",
- devpriv->i8254_osc_base, divisor1, divisor2,
- devpriv->ai_timer1);
outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
if (mode != 2) {
/* start pacer */
break;
}
- DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_docmd_and_mode(...)\n");
return 0;
}
-#ifdef PCI171X_EXTDEBUG
-/*
-==============================================================================
-*/
-static void pci171x_cmdtest_out(int e, struct comedi_cmd *cmd)
-{
- printk("adv_pci1710 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
- cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
- printk("adv_pci1710 e=%d startarg=%d scanarg=%d convarg=%d\n", e,
- cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg);
- printk("adv_pci1710 e=%d stopsrc=%x scanend=%x\n", e, cmd->stop_src,
- cmd->scan_end_src);
- printk("adv_pci1710 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n",
- e, cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len);
-}
-#endif
-
/*
==============================================================================
*/
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci1710_private *devpriv = dev->private;
int err = 0;
int tmp;
unsigned int divisor1 = 0, divisor2 = 0;
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...)\n");
-#ifdef PCI171X_EXTDEBUG
- pci171x_cmdtest_out(-1, cmd);
-#endif
/* step 1: make sure trigger sources are trivially valid */
tmp = cmd->start_src;
if (!cmd->stop_src || tmp != cmd->stop_src)
err++;
- if (err) {
-#ifdef PCI171X_EXTDEBUG
- pci171x_cmdtest_out(1, cmd);
-#endif
- DPRINTK(
- "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=1\n",
- err);
+ if (err)
return 1;
- }
/* step2: make sure trigger srcs are unique and mutually compatible */
if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
err++;
- if (err) {
-#ifdef PCI171X_EXTDEBUG
- pci171x_cmdtest_out(2, cmd);
-#endif
- DPRINTK(
- "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=2\n",
- err);
+ if (err)
return 2;
- }
/* step 3: make sure arguments are trivially compatible */
}
}
- if (err) {
-#ifdef PCI171X_EXTDEBUG
- pci171x_cmdtest_out(3, cmd);
-#endif
- DPRINTK(
- "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=3\n",
- err);
+ if (err)
return 3;
- }
/* step 4: fix up any arguments */
err++;
}
- if (err) {
- DPRINTK
- ("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=4\n",
- err);
+ if (err)
return 4;
- }
/* step 5: complain about special chanlist considerations */
return 5; /* incorrect channels list */
}
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) ret=0\n");
return 0;
}
*/
static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
+ struct pci1710_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmd(...)\n");
devpriv->ai_n_chan = cmd->chanlist_len;
devpriv->ai_chanlist = cmd->chanlist;
devpriv->ai_flags = cmd->flags;
return -1;
}
-/*
-==============================================================================
- Check if channel list from user is builded correctly
- If it's ok, then program scan/gain logic.
- This works for all cards.
-*/
-static int check_channel_list(struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned int *chanlist, unsigned int n_chan)
-{
- unsigned int chansegment[32];
- unsigned int i, nowmustbechan, seglen, segpos;
-
- DPRINTK("adv_pci1710 EDBG: check_channel_list(...,%d)\n", n_chan);
- /* correct channel and range number check itself comedi/range.c */
- if (n_chan < 1) {
- comedi_error(dev, "range/channel list is empty!");
- return 0;
- }
-
- if (n_chan == 1)
- return 1; /* seglen=1 */
-
- chansegment[0] = chanlist[0]; /* first channel is every time ok */
- for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
- if (chanlist[0] == chanlist[i])
- break; /* we detected a loop, stop */
- if ((CR_CHAN(chanlist[i]) & 1) &&
- (CR_AREF(chanlist[i]) == AREF_DIFF)) {
- comedi_error(dev, "Odd channel cannot be differential input!\n");
- return 0;
- }
- nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
- if (CR_AREF(chansegment[i - 1]) == AREF_DIFF)
- nowmustbechan = (nowmustbechan + 1) % s->n_chan;
- if (nowmustbechan != CR_CHAN(chanlist[i])) {
- printk("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
- i, CR_CHAN(chanlist[i]), nowmustbechan,
- CR_CHAN(chanlist[0]));
- return 0;
- }
- chansegment[i] = chanlist[i]; /* next correct channel in list */
- }
-
- for (i = 0, segpos = 0; i < n_chan; i++) {
- if (chanlist[i] != chansegment[i % seglen]) {
- printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
- i, CR_CHAN(chansegment[i]),
- CR_RANGE(chansegment[i]),
- CR_AREF(chansegment[i]),
- CR_CHAN(chanlist[i % seglen]),
- CR_RANGE(chanlist[i % seglen]),
- CR_AREF(chansegment[i % seglen]));
- return 0;
- }
- }
- return seglen;
-}
-
-static void setup_channel_list(struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned int *chanlist, unsigned int n_chan,
- unsigned int seglen)
-{
- unsigned int i, range, chanprog;
-
- DPRINTK("adv_pci1710 EDBG: setup_channel_list(...,%d,%d)\n", n_chan,
- seglen);
- devpriv->act_chanlist_len = seglen;
- devpriv->act_chanlist_pos = 0;
-
- DPRINTK("SegLen: %d\n", seglen);
- for (i = 0; i < seglen; i++) { /* store range list to card */
- chanprog = muxonechan[CR_CHAN(chanlist[i])];
- outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */
- range = this_board->rangecode_ai[CR_RANGE(chanlist[i])];
- if (CR_AREF(chanlist[i]) == AREF_DIFF)
- range |= 0x0020;
- outw(range, dev->iobase + PCI171x_RANGE); /* select gain */
-#ifdef PCI171x_PARANOIDCHECK
- devpriv->act_chanlist[i] =
- (CR_CHAN(chanlist[i]) << 12) & 0xf000;
-#endif
- DPRINTK("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
- devpriv->act_chanlist[i]);
- }
-#ifdef PCI171x_PARANOIDCHECK
- for ( ; i < n_chan; i++) { /* store remainder of channel list */
- devpriv->act_chanlist[i] =
- (CR_CHAN(chanlist[i]) << 12) & 0xf000;
- }
-#endif
-
- devpriv->ai_et_MuxVal =
- CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8);
- /* select channel interval to scan */
- outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX);
- DPRINTK("MUX: %4x L%4x.H%4x\n",
- CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8),
- CR_CHAN(chanlist[0]), CR_CHAN(chanlist[seglen - 1]));
-}
-
-/*
-==============================================================================
-*/
-static void start_pacer(struct comedi_device *dev, int mode,
- unsigned int divisor1, unsigned int divisor2)
-{
- DPRINTK("adv_pci1710 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode,
- divisor1, divisor2);
- outw(0xb4, dev->iobase + PCI171x_CNTCTRL);
- outw(0x74, dev->iobase + PCI171x_CNTCTRL);
-
- if (mode == 1) {
- outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2);
- outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2);
- outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1);
- outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1);
- }
- DPRINTK("adv_pci1710 EDBG: END: start_pacer(...)\n");
-}
-
-/*
-==============================================================================
-*/
-static int pci171x_ai_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s)
-{
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cancel(...)\n");
-
- switch (this_board->cardtype) {
- default:
- devpriv->CntrlReg &= Control_CNT0;
- devpriv->CntrlReg |= Control_SW;
-
- outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */
- start_pacer(dev, -1, 0, 0);
- outb(0, dev->iobase + PCI171x_CLRFIFO);
- outb(0, dev->iobase + PCI171x_CLRINT);
- break;
- }
-
- devpriv->ai_do = 0;
- devpriv->ai_act_scan = 0;
- s->async->cur_chan = 0;
- devpriv->ai_buf_ptr = 0;
- devpriv->neverending_ai = 0;
-
- DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_cancel(...)\n");
- return 0;
-}
-
/*
==============================================================================
*/
static int pci171x_reset(struct comedi_device *dev)
{
- DPRINTK("adv_pci1710 EDBG: BGN: pci171x_reset(...)\n");
+ const struct boardtype *this_board = comedi_board(dev);
+ struct pci1710_private *devpriv = dev->private;
+
outw(0x30, dev->iobase + PCI171x_CNTCTRL);
devpriv->CntrlReg = Control_SW | Control_CNT0; /* Software trigger, CNT0=external */
outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */
outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */
outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */
- DPRINTK("adv_pci1710 EDBG: END: pci171x_reset(...)\n");
return 0;
}
*/
static int pci1720_reset(struct comedi_device *dev)
{
- DPRINTK("adv_pci1710 EDBG: BGN: pci1720_reset(...)\n");
+ struct pci1710_private *devpriv = dev->private;
+
outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT); /* set synchronous output mode */
devpriv->da_ranges = 0xAA;
outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE); /* set all ranges to +/-5V */
devpriv->ao_data[1] = 0x0800;
devpriv->ao_data[2] = 0x0800;
devpriv->ao_data[3] = 0x0800;
- DPRINTK("adv_pci1710 EDBG: END: pci1720_reset(...)\n");
return 0;
}
*/
static int pci1710_reset(struct comedi_device *dev)
{
- DPRINTK("adv_pci1710 EDBG: BGN: pci1710_reset(...)\n");
+ const struct boardtype *this_board = comedi_board(dev);
+
switch (this_board->cardtype) {
case TYPE_PCI1720:
return pci1720_reset(dev);
default:
return pci171x_reset(dev);
}
- DPRINTK("adv_pci1710 EDBG: END: pci1710_reset(...)\n");
}
static struct pci_dev *pci1710_find_pci_dev(struct comedi_device *dev,
struct comedi_devconfig *it)
{
+ const struct boardtype *this_board = comedi_board(dev);
struct pci_dev *pcidev = NULL;
int bus = it->options[0];
int slot = it->options[1];
static int pci1710_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
+ const struct boardtype *this_board;
+ struct pci1710_private *devpriv;
struct pci_dev *pcidev;
struct comedi_subdevice *s;
int ret, subdev, n_subdevices;
dev_info(dev->class_dev, DRV_NAME ": attach\n");
- ret = alloc_private(dev, sizeof(struct pci1710_private));
+ ret = alloc_private(dev, sizeof(*devpriv));
if (ret < 0)
return -ENOMEM;
+ devpriv = dev->private;
pcidev = pci1710_find_pci_dev(dev, it);
if (!pcidev)
return -EIO;
comedi_set_hw_dev(dev, &pcidev->dev);
+ this_board = comedi_board(dev);
ret = comedi_pci_enable(pcidev, DRV_NAME);
if (ret)
static void pci1710_detach(struct comedi_device *dev)
{
+ struct pci1710_private *devpriv = dev->private;
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- if (dev->private) {
+ if (devpriv) {
if (devpriv->valid)
pci1710_reset(dev);
if (dev->irq)
#define PCI_VENDOR_ID_ADVANTECH 0x13fe /* Advantech PCI vendor ID */
-/* hardware types of the cards */
-#define TYPE_PCI1723 0
-
-#define IORANGE_1723 0x2A
-
/* all the registers for the pci1723 board */
#define PCI1723_DA(N) ((N)<<1) /* W: D/A register N (0 to 7) */
#define PCI1723_SELECT_CALIBRATION 0x28 /* Select the calibration Ref_V */
-/* static unsigned short pci_list_builded=0; =1 list of card is know */
-
-static const struct comedi_lrange range_pci1723 = { 1, {
- BIP_RANGE(10)
- }
-};
-
-/*
- * Board descriptions for pci1723 boards.
- */
-struct pci1723_board {
- const char *name;
- int vendor_id; /* PCI vendor a device ID of card */
- int device_id;
- int iorange;
- char cardtype;
- int n_aochan; /* num of D/A chans */
- int n_diochan; /* num of DIO chans */
- int ao_maxdata; /* resolution of D/A */
- const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
-};
-
-static const struct pci1723_board boardtypes[] = {
- {
- .name = "pci1723",
- .vendor_id = PCI_VENDOR_ID_ADVANTECH,
- .device_id = 0x1723,
- .iorange = IORANGE_1723,
- .cardtype = TYPE_PCI1723,
- .n_aochan = 8,
- .n_diochan = 16,
- .ao_maxdata = 0xffff,
- .rangelist_ao = &range_pci1723,
- },
-};
-
-/* This structure is for data unique to this hardware driver. */
struct pci1723_private {
- int valid; /* card is usable; */
-
unsigned char da_range[8]; /* D/A output range for each channel */
-
short ao_data[8]; /* data output buffer */
};
-/* The following macro to make it easy to access the private structure. */
-#define devpriv ((struct pci1723_private *)dev->private)
-
-#define this_board boardtypes
-
/*
* The pci1723 card reset;
*/
static int pci1723_reset(struct comedi_device *dev)
{
+ struct pci1723_private *devpriv = dev->private;
int i;
- DPRINTK("adv_pci1723 EDBG: BGN: pci1723_reset(...)\n");
outw(0x01, dev->iobase + PCI1723_SYN_SET);
/* set synchronous output mode */
/* set asynchronous output mode */
outw(0, dev->iobase + PCI1723_SYN_SET);
- DPRINTK("adv_pci1723 EDBG: END: pci1723_reset(...)\n");
return 0;
}
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci1723_private *devpriv = dev->private;
int n, chan;
chan = CR_CHAN(insn->chanspec);
- DPRINTK(" adv_PCI1723 DEBUG: pci1723_insn_read_ao() -----\n");
for (n = 0; n < insn->n; n++)
data[n] = devpriv->ao_data[chan];
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci1723_private *devpriv = dev->private;
int n, chan;
chan = CR_CHAN(insn->chanspec);
- DPRINTK("PCI1723: the pci1723_ao_write_winsn() ------\n");
-
for (n = 0; n < insn->n; n++) {
devpriv->ao_data[chan] = data[n];
return insn->n;
}
-static struct pci_dev *pci1723_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int pci1723_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_ADVANTECH)
- continue;
- return pcidev;
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-static int pci1723_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
+ struct pci1723_private *devpriv;
struct comedi_subdevice *s;
- int ret, subdev, n_subdevices;
+ int ret;
- printk(KERN_ERR "comedi%d: adv_pci1723: board=%s",
- dev->minor, this_board->name);
-
- ret = alloc_private(dev, sizeof(struct pci1723_private));
- if (ret < 0) {
- printk(" - Allocation failed!\n");
- return -ENOMEM;
- }
-
- pcidev = pci1723_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
comedi_set_hw_dev(dev, &pcidev->dev);
+ dev->board_name = dev->driver->driver_name;
- ret = comedi_pci_enable(pcidev, "adv_pci1723");
- if (ret)
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret < 0)
return ret;
+ devpriv = dev->private;
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
dev->iobase = pci_resource_start(pcidev, 2);
- dev->board_name = this_board->name;
-
- n_subdevices = 0;
-
- if (this_board->n_aochan)
- n_subdevices++;
- if (this_board->n_diochan)
- n_subdevices++;
-
- ret = comedi_alloc_subdevices(dev, n_subdevices);
+ ret = comedi_alloc_subdevices(dev, 2);
if (ret)
return ret;
- pci1723_reset(dev);
- subdev = 0;
- if (this_board->n_aochan) {
- s = dev->subdevices + subdev;
- dev->write_subdev = s;
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = this_board->n_aochan;
- s->maxdata = this_board->ao_maxdata;
- s->len_chanlist = this_board->n_aochan;
- s->range_table = this_board->rangelist_ao;
-
- s->insn_write = pci1723_ao_write_winsn;
- s->insn_read = pci1723_insn_read_ao;
-
- /* read DIO config */
- switch (inw(dev->iobase + PCI1723_DIGITAL_IO_PORT_MODE)
- & 0x03) {
- case 0x00: /* low byte output, high byte output */
- s->io_bits = 0xFFFF;
- break;
- case 0x01: /* low byte input, high byte output */
- s->io_bits = 0xFF00;
- break;
- case 0x02: /* low byte output, high byte input */
- s->io_bits = 0x00FF;
- break;
- case 0x03: /* low byte input, high byte input */
- s->io_bits = 0x0000;
- break;
- }
- /* read DIO port state */
- s->state = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA);
-
- subdev++;
- }
-
- if (this_board->n_diochan) {
- s = dev->subdevices + subdev;
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags =
- SDF_READABLE | SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
- s->n_chan = this_board->n_diochan;
- s->maxdata = 1;
- s->len_chanlist = this_board->n_diochan;
- s->range_table = &range_digital;
- s->insn_config = pci1723_dio_insn_config;
- s->insn_bits = pci1723_dio_insn_bits;
- subdev++;
+ s = dev->subdevices + 0;
+ dev->write_subdev = s;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
+ s->n_chan = 8;
+ s->maxdata = 0xffff;
+ s->len_chanlist = 8;
+ s->range_table = &range_bipolar10;
+ s->insn_write = pci1723_ao_write_winsn;
+ s->insn_read = pci1723_insn_read_ao;
+
+ s = dev->subdevices + 1;
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->len_chanlist = 16;
+ s->range_table = &range_digital;
+ s->insn_config = pci1723_dio_insn_config;
+ s->insn_bits = pci1723_dio_insn_bits;
+
+ /* read DIO config */
+ switch (inw(dev->iobase + PCI1723_DIGITAL_IO_PORT_MODE) & 0x03) {
+ case 0x00: /* low byte output, high byte output */
+ s->io_bits = 0xFFFF;
+ break;
+ case 0x01: /* low byte input, high byte output */
+ s->io_bits = 0xFF00;
+ break;
+ case 0x02: /* low byte output, high byte input */
+ s->io_bits = 0x00FF;
+ break;
+ case 0x03: /* low byte input, high byte input */
+ s->io_bits = 0x0000;
+ break;
}
-
- devpriv->valid = 1;
+ /* read DIO port state */
+ s->state = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA);
pci1723_reset(dev);
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+
return 0;
}
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- if (dev->private) {
- if (devpriv->valid)
- pci1723_reset(dev);
- }
if (pcidev) {
- if (dev->iobase)
+ if (dev->iobase) {
+ pci1723_reset(dev);
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
+ }
}
}
static struct comedi_driver adv_pci1723_driver = {
.driver_name = "adv_pci1723",
.module = THIS_MODULE,
- .attach = pci1723_attach,
+ .attach_pci = pci1723_attach_pci,
.detach = pci1723_detach,
};
#include "8255.h"
#include "8253.h"
-#undef PCI_DIO_EXTDEBUG /* if defined, enable extensive debug logging */
-
-#undef DPRINTK
-#ifdef PCI_DIO_EXTDEBUG
-#define DPRINTK(fmt, args...) printk(fmt, ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
#define PCI_VENDOR_ID_ADVANTECH 0x13fe
/* hardware types of the cards */
int device_id;
int main_pci_region; /* main I/O PCI region */
enum hw_cards_id cardtype;
+ int nsubdevs;
struct diosubd_data sdi[MAX_DI_SUBDEVS]; /* DI chans */
struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */
struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */
};
static const struct dio_boardtype boardtypes[] = {
- {"pci1730", PCI_VENDOR_ID_ADVANTECH, 0x1730, PCIDIO_MAINREG,
- TYPE_PCI1730,
- { {16, PCI1730_DI, 2, 0}, {16, PCI1730_IDI, 2, 0} },
- { {16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG,
- TYPE_PCI1733,
- { {0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG,
- TYPE_PCI1734,
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG,
- TYPE_PCI1735,
- { {32, PCI1735_DI, 4, 0}, {0, 0, 0, 0} },
- { {32, PCI1735_DO, 4, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { 4, PCI1735_BOARDID, 1, SDF_INTERNAL},
- { {3, PCI1735_C8254, 1, 0} },
- IO_8b},
- {"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG,
- TYPE_PCI1736,
- { {0, 0, 0, 0}, {16, PCI1736_IDI, 2, 0} },
- { {0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI1736_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1739", PCI_VENDOR_ID_ADVANTECH, 0x1739, PCIDIO_MAINREG,
- TYPE_PCI1739,
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {48, PCI1739_DIO, 2, 0}, {0, 0, 0, 0} },
- {0, 0, 0, 0},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG,
- TYPE_PCI1750,
- { {0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0} },
- { {0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {0, 0, 0, 0},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG,
- TYPE_PCI1751,
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0} },
- {0, 0, 0, 0},
- { {3, PCI1751_CNT, 1, 0} },
- IO_8b},
- {"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG,
- TYPE_PCI1752,
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_16b},
- {"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
- TYPE_PCI1753,
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0} },
- {0, 0, 0, 0},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
- TYPE_PCI1753E,
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0} },
- {0, 0, 0, 0},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG,
- TYPE_PCI1754,
- { {32, PCI1754_IDI, 2, 0}, {32, PCI1754_IDI2, 2, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_16b},
- {"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG,
- TYPE_PCI1756,
- { {0, 0, 0, 0}, {32, PCI1756_IDI, 2, 0} },
- { {0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_16b},
- {"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
- TYPE_PCI1760,
- { {0, 0, 0, 0}, {0, 0, 0, 0} }, /* This card have own setup work */
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {0, 0, 0, 0},
- { {0, 0, 0, 0} },
- IO_8b},
- {"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG,
- TYPE_PCI1762,
- { {0, 0, 0, 0}, {16, PCI1762_IDI, 1, 0} },
- { {0, 0, 0, 0}, {16, PCI1762_RO, 1, 0} },
- { {0, 0, 0, 0}, {0, 0, 0, 0} },
- {4, PCI1762_BOARDID, 1, SDF_INTERNAL},
- { {0, 0, 0, 0} },
- IO_16b}
+ {
+ .name = "pci1730",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1730,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1730,
+ .nsubdevs = 5,
+ .sdi[0] = { 16, PCI1730_DI, 2, 0, },
+ .sdi[1] = { 16, PCI1730_IDI, 2, 0, },
+ .sdo[0] = { 16, PCI1730_DO, 2, 0, },
+ .sdo[1] = { 16, PCI1730_IDO, 2, 0, },
+ .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1733",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1733,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1733,
+ .nsubdevs = 2,
+ .sdi[1] = { 32, PCI1733_IDI, 4, 0, },
+ .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1734",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1734,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1734,
+ .nsubdevs = 2,
+ .sdo[1] = { 32, PCI1734_IDO, 4, 0, },
+ .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1735",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1735,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1735,
+ .nsubdevs = 4,
+ .sdi[0] = { 32, PCI1735_DI, 4, 0, },
+ .sdo[0] = { 32, PCI1735_DO, 4, 0, },
+ .boardid = { 4, PCI1735_BOARDID, 1, SDF_INTERNAL, },
+ .s8254[0] = { 3, PCI1735_C8254, 1, 0, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1736",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1736,
+ .main_pci_region = PCI1736_MAINREG,
+ .cardtype = TYPE_PCI1736,
+ .nsubdevs = 3,
+ .sdi[1] = { 16, PCI1736_IDI, 2, 0, },
+ .sdo[1] = { 16, PCI1736_IDO, 2, 0, },
+ .boardid = { 4, PCI1736_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1739",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1739,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1739,
+ .nsubdevs = 2,
+ .sdio[0] = { 48, PCI1739_DIO, 2, 0, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1750",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1750,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1750,
+ .nsubdevs = 2,
+ .sdi[1] = { 16, PCI1750_IDI, 2, 0, },
+ .sdo[1] = { 16, PCI1750_IDO, 2, 0, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1751",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1751,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1751,
+ .nsubdevs = 3,
+ .sdio[0] = { 48, PCI1751_DIO, 2, 0, },
+ .s8254[0] = { 3, PCI1751_CNT, 1, 0, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1752",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1752,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1752,
+ .nsubdevs = 3,
+ .sdo[0] = { 32, PCI1752_IDO, 2, 0, },
+ .sdo[1] = { 32, PCI1752_IDO2, 2, 0, },
+ .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_16b,
+ }, {
+ .name = "pci1753",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1753,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1753,
+ .nsubdevs = 4,
+ .sdio[0] = { 96, PCI1753_DIO, 4, 0, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1753e",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1753,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1753E,
+ .nsubdevs = 8,
+ .sdio[0] = { 96, PCI1753_DIO, 4, 0, },
+ .sdio[1] = { 96, PCI1753E_DIO, 4, 0, },
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1754",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1754,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1754,
+ .nsubdevs = 3,
+ .sdi[0] = { 32, PCI1754_IDI, 2, 0, },
+ .sdi[1] = { 32, PCI1754_IDI2, 2, 0, },
+ .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_16b,
+ }, {
+ .name = "pci1756",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1756,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1756,
+ .nsubdevs = 3,
+ .sdi[1] = { 32, PCI1756_IDI, 2, 0, },
+ .sdo[1] = { 32, PCI1756_IDO, 2, 0, },
+ .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_16b,
+ }, {
+ /* This card has its own 'attach' */
+ .name = "pci1760",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1760,
+ .main_pci_region = 0,
+ .cardtype = TYPE_PCI1760,
+ .nsubdevs = 4,
+ .io_access = IO_8b,
+ }, {
+ .name = "pci1762",
+ .vendor_id = PCI_VENDOR_ID_ADVANTECH,
+ .device_id = 0x1762,
+ .main_pci_region = PCIDIO_MAINREG,
+ .cardtype = TYPE_PCI1762,
+ .nsubdevs = 3,
+ .sdi[1] = { 16, PCI1762_IDI, 1, 0, },
+ .sdo[1] = { 16, PCI1762_RO, 1, 0, },
+ .boardid = { 4, PCI1762_BOARDID, 1, SDF_INTERNAL, },
+ .io_access = IO_16b,
+ },
};
struct pci_dio_private {
unsigned short IDIFiltrHigh[8]; /* IDI's filter value high signal */
};
-#define devpriv ((struct pci_dio_private *)dev->private)
-#define this_board ((const struct dio_boardtype *)dev->board_ptr)
-
/*
==============================================================================
*/
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct pci_dio_private *devpriv = dev->private;
int ret;
unsigned char chan = CR_CHAN(insn->chanspec) & 0x07;
unsigned char bitmask = 1 << chan;
*/
static int pci1760_reset(struct comedi_device *dev)
{
+ struct pci_dio_private *devpriv = dev->private;
int i;
unsigned char omb[4] = { 0x00, 0x00, 0x00, 0x00 };
unsigned char imb[4];
*/
static int pci_dio_reset(struct comedi_device *dev)
{
- DPRINTK("adv_pci_dio EDBG: BGN: pci171x_reset(...)\n");
+ const struct dio_boardtype *this_board = comedi_board(dev);
switch (this_board->cardtype) {
case TYPE_PCI1730:
break;
}
- DPRINTK("adv_pci_dio EDBG: END: pci171x_reset(...)\n");
-
return 0;
}
/*
==============================================================================
*/
-static int pci1760_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int pci1760_attach(struct comedi_device *dev)
{
struct comedi_subdevice *s;
int subdev = 0;
static int pci_dio_add_di(struct comedi_device *dev, struct comedi_subdevice *s,
const struct diosubd_data *d, int subdev)
{
+ const struct dio_boardtype *this_board = comedi_board(dev);
+
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON | d->specflags;
if (d->chans > 16)
static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s,
const struct diosubd_data *d, int subdev)
{
+ const struct dio_boardtype *this_board = comedi_board(dev);
+
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
if (d->chans > 16)
return 0;
}
-static struct pci_dev *pci_dio_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *pci_dio_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
+ const struct dio_boardtype *this_board;
int i;
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
- if (boardtypes[i].vendor_id != pcidev->vendor)
- continue;
- if (boardtypes[i].device_id != pcidev->device)
- continue;
- dev->board_ptr = boardtypes + i;
- return pcidev;
- }
+ for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
+ this_board = &boardtypes[i];
+ if (this_board->vendor_id == pcidev->vendor &&
+ this_board->device_id == pcidev->device)
+ return this_board;
}
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
return NULL;
}
-static int pci_dio_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int pci_dio_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev;
+ const struct dio_boardtype *this_board;
+ struct pci_dio_private *devpriv;
struct comedi_subdevice *s;
- int ret, subdev, n_subdevices, i, j;
+ int ret, subdev, i, j;
- ret = alloc_private(dev, sizeof(struct pci_dio_private));
- if (ret < 0)
- return -ENOMEM;
-
- pcidev = pci_dio_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
comedi_set_hw_dev(dev, &pcidev->dev);
- if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
- dev_err(dev->class_dev,
- "Error: Can't enable PCI device and request regions!\n");
- return -EIO;
- }
-
- dev->iobase = pci_resource_start(pcidev, this_board->main_pci_region);
+ this_board = pci_dio_find_boardinfo(dev, pcidev);
+ if (!this_board)
+ return -ENODEV;
+ dev->board_ptr = this_board;
dev->board_name = this_board->name;
- if (this_board->cardtype == TYPE_PCI1760) {
- n_subdevices = 4; /* 8 IDI, 8 IDO, 2 PWM, 8 CNT */
- } else {
- n_subdevices = 0;
- for (i = 0; i < MAX_DI_SUBDEVS; i++)
- if (this_board->sdi[i].chans)
- n_subdevices++;
- for (i = 0; i < MAX_DO_SUBDEVS; i++)
- if (this_board->sdo[i].chans)
- n_subdevices++;
- for (i = 0; i < MAX_DIO_SUBDEVG; i++)
- n_subdevices += this_board->sdio[i].regs;
- if (this_board->boardid.chans)
- n_subdevices++;
- for (i = 0; i < MAX_8254_SUBDEVS; i++)
- if (this_board->s8254[i].chans)
- n_subdevices++;
- }
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret < 0)
+ return ret;
+ devpriv = dev->private;
- ret = comedi_alloc_subdevices(dev, n_subdevices);
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+ dev->iobase = pci_resource_start(pcidev, this_board->main_pci_region);
+
+ ret = comedi_alloc_subdevices(dev, this_board->nsubdevs);
if (ret)
return ret;
}
if (this_board->cardtype == TYPE_PCI1760)
- pci1760_attach(dev, it);
+ pci1760_attach(dev);
devpriv->valid = 1;
static void pci_dio_detach(struct comedi_device *dev)
{
+ struct pci_dio_private *devpriv = dev->private;
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- int i, j;
struct comedi_subdevice *s;
- int subdev;
+ int i;
- if (dev->private) {
+ if (devpriv) {
if (devpriv->valid)
pci_dio_reset(dev);
- subdev = 0;
- for (i = 0; i < MAX_DI_SUBDEVS; i++) {
- if (this_board->sdi[i].chans)
- subdev++;
- }
- for (i = 0; i < MAX_DO_SUBDEVS; i++) {
- if (this_board->sdo[i].chans)
- subdev++;
- }
- for (i = 0; i < MAX_DIO_SUBDEVG; i++) {
- for (j = 0; j < this_board->sdio[i].regs; j++) {
- s = dev->subdevices + subdev;
- subdev_8255_cleanup(dev, s);
- subdev++;
- }
- }
- if (this_board->boardid.chans)
- subdev++;
- for (i = 0; i < MAX_8254_SUBDEVS; i++)
- if (this_board->s8254[i].chans)
- subdev++;
+ }
+ if (dev->subdevices) {
for (i = 0; i < dev->n_subdevices; i++) {
s = dev->subdevices + i;
+ if (s->type == COMEDI_SUBD_DIO)
+ subdev_8255_cleanup(dev, s);
s->private = NULL;
}
}
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver adv_pci_dio_driver = {
.driver_name = "adv_pci_dio",
.module = THIS_MODULE,
- .attach = pci_dio_attach,
- .detach = pci_dio_detach
+ .attach_pci = pci_dio_attach_pci,
+ .detach = pci_dio_detach,
};
static int __devinit adv_pci_dio_pci_probe(struct pci_dev *dev,
Driver: aio_aio12_8
Description: Access I/O Products PC-104 AIO12-8 Analog I/O Board
Author: Pablo Mejia <pablo.mejia@cctechnol.com>
-Devices:
- [Access I/O] PC-104 AIO12-8
+Devices: [Access I/O] PC-104 AIO12-8 (aio_aio12_8)
+ [Access I/O] PC-104 AI12-8 (aio_ai12_8)
+ [Access I/O] PC-104 AO12-8 (aio_ao12_8)
Status: experimental
Configuration Options:
#include <linux/ioport.h>
#include "8255.h"
-#define AIO12_8_STATUS 0x00
-#define AIO12_8_INTERRUPT 0x01
-#define AIO12_8_ADC 0x02
-#define AIO12_8_DAC_0 0x04
-#define AIO12_8_DAC_1 0x06
-#define AIO12_8_DAC_2 0x08
-#define AIO12_8_DAC_3 0x0A
-#define AIO12_8_COUNTER_0 0x0C
-#define AIO12_8_COUNTER_1 0x0D
-#define AIO12_8_COUNTER_2 0x0E
-#define AIO12_8_COUNTER_CONTROL 0x0F
-#define AIO12_8_DIO_0 0x10
-#define AIO12_8_DIO_1 0x11
-#define AIO12_8_DIO_2 0x12
-#define AIO12_8_DIO_STATUS 0x13
-#define AIO12_8_DIO_CONTROL 0x14
-#define AIO12_8_ADC_TRIGGER_CONTROL 0x15
-#define AIO12_8_TRIGGER 0x16
-#define AIO12_8_POWER 0x17
-
-#define STATUS_ADC_EOC 0x80
-
-#define ADC_MODE_NORMAL 0x00
-#define ADC_MODE_INTERNAL_CLOCK 0x40
-#define ADC_MODE_STANDBY 0x80
-#define ADC_MODE_POWERDOWN 0xC0
-
-#define DAC_ENABLE 0x18
+/*
+ * Register map
+ */
+#define AIO12_8_STATUS_REG 0x00
+#define AIO12_8_STATUS_ADC_EOC (1 << 7)
+#define AIO12_8_STATUS_PORT_C_COS (1 << 6)
+#define AIO12_8_STATUS_IRQ_ENA (1 << 2)
+#define AIO12_8_INTERRUPT_REG 0x01
+#define AIO12_8_INTERRUPT_ADC (1 << 7)
+#define AIO12_8_INTERRUPT_COS (1 << 6)
+#define AIO12_8_INTERRUPT_COUNTER1 (1 << 5)
+#define AIO12_8_INTERRUPT_PORT_C3 (1 << 4)
+#define AIO12_8_INTERRUPT_PORT_C0 (1 << 3)
+#define AIO12_8_INTERRUPT_ENA (1 << 2)
+#define AIO12_8_ADC_REG 0x02
+#define AIO12_8_ADC_MODE_NORMAL (0 << 6)
+#define AIO12_8_ADC_MODE_INT_CLK (1 << 6)
+#define AIO12_8_ADC_MODE_STANDBY (2 << 6)
+#define AIO12_8_ADC_MODE_POWERDOWN (3 << 6)
+#define AIO12_8_ADC_ACQ_3USEC (0 << 5)
+#define AIO12_8_ADC_ACQ_PROGRAM (1 << 5)
+#define AIO12_8_ADC_RANGE(x) ((x) << 3)
+#define AIO12_8_ADC_CHAN(x) ((x) << 0)
+#define AIO12_8_DAC_REG(x) (0x04 + (x) * 2)
+#define AIO12_8_8254_BASE_REG 0x0c
+#define AIO12_8_8255_BASE_REG 0x10
+#define AIO12_8_DIO_CONTROL_REG 0x14
+#define AIO12_8_DIO_CONTROL_TST (1 << 0)
+#define AIO12_8_ADC_TRIGGER_REG 0x15
+#define AIO12_8_ADC_TRIGGER_RANGE(x) ((x) << 3)
+#define AIO12_8_ADC_TRIGGER_CHAN(x) ((x) << 0)
+#define AIO12_8_TRIGGER_REG 0x16
+#define AIO12_8_TRIGGER_ADTRIG (1 << 1)
+#define AIO12_8_TRIGGER_DACTRIG (1 << 0)
+#define AIO12_8_COS_REG 0x17
+#define AIO12_8_DAC_ENABLE_REG 0x18
+#define AIO12_8_DAC_ENABLE_REF_ENA (1 << 0)
struct aio12_8_boardtype {
const char *name;
+ int ai_nchan;
+ int ao_nchan;
};
static const struct aio12_8_boardtype board_types[] = {
{
- .name = "aio_aio12_8"},
+ .name = "aio_aio12_8",
+ .ai_nchan = 8,
+ .ao_nchan = 4,
+ }, {
+ .name = "aio_ai12_8",
+ .ai_nchan = 8,
+ }, {
+ .name = "aio_ao12_8",
+ .ao_nchan = 4,
+ },
};
struct aio12_8_private {
unsigned int ao_readback[4];
};
-#define devpriv ((struct aio12_8_private *) dev->private)
-
static int aio_aio12_8_ai_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int val;
+ unsigned char control;
int n;
- unsigned char control =
- ADC_MODE_NORMAL |
- (CR_RANGE(insn->chanspec) << 3) | CR_CHAN(insn->chanspec);
- /* read status to clear EOC latch */
- inb(dev->iobase + AIO12_8_STATUS);
+ /*
+ * Setup the control byte for internal 2MHz clock, 3uS conversion,
+ * at the desired range of the requested channel.
+ */
+ control = AIO12_8_ADC_MODE_NORMAL | AIO12_8_ADC_ACQ_3USEC |
+ AIO12_8_ADC_RANGE(range) | AIO12_8_ADC_CHAN(chan);
+
+ /* Read status to clear EOC latch */
+ inb(dev->iobase + AIO12_8_STATUS_REG);
for (n = 0; n < insn->n; n++) {
int timeout = 5;
/* Setup and start conversion */
- outb(control, dev->iobase + AIO12_8_ADC);
+ outb(control, dev->iobase + AIO12_8_ADC_REG);
/* Wait for conversion to complete */
- while (timeout &&
- !(inb(dev->iobase + AIO12_8_STATUS) & STATUS_ADC_EOC)) {
+ do {
+ val = inb(dev->iobase + AIO12_8_STATUS_REG);
timeout--;
- printk(KERN_ERR "timeout %d\n", timeout);
- udelay(1);
- }
- if (timeout == 0) {
- comedi_error(dev, "ADC timeout");
- return -EIO;
- }
-
- data[n] = inw(dev->iobase + AIO12_8_ADC) & 0x0FFF;
+ if (timeout == 0) {
+ dev_err(dev->class_dev, "ADC timeout\n");
+ return -ETIMEDOUT;
+ }
+ } while (!(val & AIO12_8_STATUS_ADC_EOC));
+
+ data[n] = inw(dev->iobase + AIO12_8_ADC_REG) & s->maxdata;
}
- return n;
+
+ return insn->n;
}
static int aio_aio12_8_ao_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct aio12_8_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ int val = devpriv->ao_readback[chan];
int i;
- int val = devpriv->ao_readback[CR_CHAN(insn->chanspec)];
for (i = 0; i < insn->n; i++)
data[i] = val;
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct aio12_8_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned long port = dev->iobase + AIO12_8_DAC_REG(chan);
+ unsigned int val = 0;
int i;
- int chan = CR_CHAN(insn->chanspec);
- unsigned long port = dev->iobase + AIO12_8_DAC_0 + (2 * chan);
/* enable DACs */
- outb(0x01, dev->iobase + DAC_ENABLE);
+ outb(AIO12_8_DAC_ENABLE_REF_ENA, dev->iobase + AIO12_8_DAC_ENABLE_REG);
for (i = 0; i < insn->n; i++) {
- outb(data[i] & 0xFF, port); /* LSB */
- outb((data[i] >> 8) & 0x0F, port + 1); /* MSB */
- devpriv->ao_readback[chan] = data[i];
+ val = data[i];
+ outw(val, port);
}
+
+ devpriv->ao_readback[chan] = val;
+
return insn->n;
}
struct comedi_devconfig *it)
{
const struct aio12_8_boardtype *board = comedi_board(dev);
- int iobase;
+ struct aio12_8_private *devpriv;
struct comedi_subdevice *s;
+ int iobase;
int ret;
+ dev->board_name = board->name;
+
iobase = it->options[0];
- if (!request_region(iobase, 24, "aio_aio12_8")) {
+ if (!request_region(iobase, 32, dev->board_name)) {
printk(KERN_ERR "I/O port conflict");
return -EIO;
}
+ dev->iobase = iobase;
- dev->board_name = board->name;
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
- dev->iobase = iobase;
+ ret = comedi_alloc_subdevices(dev, 4);
+ if (ret)
+ return ret;
- if (alloc_private(dev, sizeof(struct aio12_8_private)) < 0)
- return -ENOMEM;
+ s = dev->subdevices + 0;
+ if (board->ai_nchan) {
+ /* Analog input subdevice */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
+ s->n_chan = board->ai_nchan;
+ s->maxdata = 0x0fff;
+ s->range_table = &range_aio_aio12_8;
+ s->insn_read = aio_aio12_8_ai_read;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
- ret = comedi_alloc_subdevices(dev, 3);
+ s = dev->subdevices + 1;
+ if (board->ao_nchan) {
+ /* Analog output subdevice */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_DIFF;
+ s->n_chan = 4;
+ s->maxdata = 0x0fff;
+ s->range_table = &range_aio_aio12_8;
+ s->insn_read = aio_aio12_8_ao_read;
+ s->insn_write = aio_aio12_8_ao_write;
+ } else {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ s = dev->subdevices + 2;
+ /* 8255 Digital i/o subdevice */
+ iobase = dev->iobase + AIO12_8_8255_BASE_REG;
+ ret = subdev_8255_init(dev, s, NULL, iobase);
if (ret)
return ret;
- s = &dev->subdevices[0];
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
- s->n_chan = 8;
- s->maxdata = (1 << 12) - 1;
- s->range_table = &range_aio_aio12_8;
- s->insn_read = aio_aio12_8_ai_read;
-
- s = &dev->subdevices[1];
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_DIFF;
- s->n_chan = 4;
- s->maxdata = (1 << 12) - 1;
- s->range_table = &range_aio_aio12_8;
- s->insn_read = aio_aio12_8_ao_read;
- s->insn_write = aio_aio12_8_ao_write;
-
- s = &dev->subdevices[2];
- subdev_8255_init(dev, s, NULL, dev->iobase + AIO12_8_DIO_0);
+ s = dev->subdevices + 3;
+ /* 8254 counter/timer subdevice */
+ s->type = COMEDI_SUBD_UNUSED;
+
+ dev_info(dev->class_dev, "%s: %s attached\n",
+ dev->driver->driver_name, dev->board_name);
return 0;
}
static void aio_aio12_8_detach(struct comedi_device *dev)
{
- subdev_8255_cleanup(dev, &dev->subdevices[2]);
+ if (dev->subdevices)
+ subdev_8255_cleanup(dev, dev->subdevices + 2);
if (dev->iobase)
release_region(dev->iobase, 24);
}
#define DIO200_DRIVER_NAME "amplc_dio200"
+#define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
+#define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
+
/* PCI IDs */
#define PCI_VENDOR_ID_AMPLICON 0x14dc
#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
};
enum dio200_layout {
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
+#if DO_ISA
pc212_layout,
pc214_layout,
#endif
pc215_layout,
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
+#if DO_ISA
pc218_layout,
#endif
pc272_layout
};
static const struct dio200_board dio200_boards[] = {
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
+#if DO_ISA
{
.name = "pc212e",
.bustype = isa_bustype,
.layout = pc272_layout,
},
#endif
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
+#if DO_PCI
{
.name = "pci215",
.devid = PCI_DEVICE_ID_AMPLICON_PCI215,
};
static const struct dio200_layout_struct dio200_layouts[] = {
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
+#if DO_ISA
[pc212_layout] = {
.n_subdevs = 6,
.sdtype = {sd_8255, sd_8254, sd_8254, sd_8254,
.has_int_sce = 1,
.has_clk_gat_sce = 1,
},
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
+#if DO_ISA
[pc218_layout] = {
.n_subdevs = 7,
.sdtype = {sd_8254, sd_8254, sd_8255, sd_8254,
int continuous;
};
+static inline bool is_pci_board(const struct dio200_board *board)
+{
+ return DO_PCI && board->bustype == pci_bustype;
+}
+
+static inline bool is_isa_board(const struct dio200_board *board)
+{
+ return DO_ISA && board->bustype == isa_bustype;
+}
+
/*
* This function looks for a board matching the supplied PCI device.
*/
unsigned int i;
for (i = 0; i < ARRAY_SIZE(dio200_boards); i++)
- if (dio200_boards[i].bustype == pci_bustype &&
+ if (is_pci_board(&dio200_boards[i]) &&
pci_dev->device == dio200_boards[i].devid)
return &dio200_boards[i];
return NULL;
char tmpbuf[60];
int tmplen;
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) &&
- thisboard->bustype == isa_bustype)
+ if (is_isa_board(thisboard))
tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
"(base %#lx) ", dev->iobase);
- else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) &&
- thisboard->bustype == pci_bustype)
+ else if (is_pci_board(thisboard))
tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
"(pci %s) ", pci_name(pcidev));
else
}
/* Process options and reserve resources according to bus type. */
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) &&
- thisboard->bustype == isa_bustype) {
+ if (is_isa_board(thisboard)) {
unsigned long iobase;
unsigned int irq;
if (ret < 0)
return ret;
return dio200_common_attach(dev, iobase, irq, 0);
- } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) &&
- thisboard->bustype == pci_bustype) {
+ } else if (is_pci_board(thisboard)) {
struct pci_dev *pci_dev;
pci_dev = dio200_find_pci_dev(dev, it);
{
int ret;
- if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI))
+ if (!DO_PCI)
return -EINVAL;
dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach pci %s\n",
static void dio200_detach(struct comedi_device *dev)
{
const struct dio200_board *thisboard = comedi_board(dev);
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
const struct dio200_layout_struct *layout;
unsigned n;
}
}
}
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- } else {
+ if (is_isa_board(thisboard)) {
if (dev->iobase)
release_region(dev->iobase, DIO200_IO_SIZE);
+ } else if (is_pci_board(thisboard)) {
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ pci_dev_put(pcidev);
+ }
}
}
.num_names = ARRAY_SIZE(dio200_boards),
};
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
+#if DO_PCI
static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) },
#define PC236_DRIVER_NAME "amplc_pc236"
+#define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA)
+#define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI)
+
/* PCI236 PCI configuration register information */
#define PCI_VENDOR_ID_AMPLICON 0x14dc
#define PCI_DEVICE_ID_AMPLICON_PCI236 0x0009
enum pc236_model model;
};
static const struct pc236_board pc236_boards[] = {
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA)
+#if DO_ISA
{
.name = "pc36at",
.bustype = isa_bustype,
.model = pc36at_model,
},
#endif
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI)
+#if DO_PCI
{
.name = "pci236",
.devid = PCI_DEVICE_ID_AMPLICON_PCI236,
int enable_irq;
};
+/* test if ISA supported and this is an ISA board */
+static inline bool is_isa_board(const struct pc236_board *board)
+{
+ return DO_ISA && board->bustype == isa_bustype;
+}
+
+/* test if PCI supported and this is a PCI board */
+static inline bool is_pci_board(const struct pc236_board *board)
+{
+ return DO_PCI && board->bustype == pci_bustype;
+}
+
/*
* This function looks for a board matching the supplied PCI device.
*/
unsigned int i;
for (i = 0; i < ARRAY_SIZE(pc236_boards); i++)
- if (pc236_boards[i].bustype == pci_bustype &&
+ if (is_pci_board(&pc236_boards[i]) &&
pci_dev->device == pc236_boards[i].devid)
return &pc236_boards[i];
return NULL;
*/
static void pc236_intr_disable(struct comedi_device *dev)
{
+ const struct pc236_board *thisboard = comedi_board(dev);
struct pc236_private *devpriv = dev->private;
unsigned long flags;
spin_lock_irqsave(&dev->spinlock, flags);
devpriv->enable_irq = 0;
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && devpriv->lcr_iobase)
+ if (is_pci_board(thisboard))
outl(PCI236_INTR_DISABLE, devpriv->lcr_iobase + PLX9052_INTCSR);
spin_unlock_irqrestore(&dev->spinlock, flags);
}
*/
static void pc236_intr_enable(struct comedi_device *dev)
{
+ const struct pc236_board *thisboard = comedi_board(dev);
struct pc236_private *devpriv = dev->private;
unsigned long flags;
spin_lock_irqsave(&dev->spinlock, flags);
devpriv->enable_irq = 1;
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) && devpriv->lcr_iobase)
+ if (is_pci_board(thisboard))
outl(PCI236_INTR_ENABLE, devpriv->lcr_iobase + PLX9052_INTCSR);
spin_unlock_irqrestore(&dev->spinlock, flags);
}
*/
static int pc236_intr_check(struct comedi_device *dev)
{
+ const struct pc236_board *thisboard = comedi_board(dev);
struct pc236_private *devpriv = dev->private;
int retval = 0;
unsigned long flags;
spin_lock_irqsave(&dev->spinlock, flags);
if (devpriv->enable_irq) {
retval = 1;
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) &&
- devpriv->lcr_iobase) {
+ if (is_pci_board(thisboard)) {
if ((inl(devpriv->lcr_iobase + PLX9052_INTCSR)
& PLX9052_INTCSR_LI1STAT_MASK)
== PLX9052_INTCSR_LI1STAT_INACTIVE) {
char tmpbuf[60];
int tmplen;
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) &&
- thisboard->bustype == isa_bustype)
+ if (is_isa_board(thisboard))
tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
"(base %#lx) ", dev->iobase);
- else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) &&
- thisboard->bustype == pci_bustype) {
+ else if (is_pci_board(thisboard))
tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
"(pci %s) ", pci_name(pcidev));
- } else
+ else
tmplen = 0;
if (irq)
tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen,
return ret;
}
/* Process options according to bus type. */
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_ISA) &&
- thisboard->bustype == isa_bustype) {
+ if (is_isa_board(thisboard)) {
unsigned long iobase = it->options[0];
unsigned int irq = it->options[1];
ret = pc236_request_region(dev, iobase, PC236_IO_SIZE);
if (ret < 0)
return ret;
return pc236_common_attach(dev, iobase, irq, 0);
- } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI) &&
- thisboard->bustype == pci_bustype) {
+ } else if (is_pci_board(thisboard)) {
struct pci_dev *pci_dev;
pci_dev = pc236_find_pci_dev(dev, it);
{
int ret;
- if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI))
+ if (!DO_PCI)
return -EINVAL;
dev_info(dev->class_dev, PC236_DRIVER_NAME ": attach pci %s\n",
static void pc236_detach(struct comedi_device *dev)
{
+ const struct pc236_board *thisboard = comedi_board(dev);
struct pc236_private *devpriv = dev->private;
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
if (devpriv)
pc236_intr_disable(dev);
free_irq(dev->irq, dev);
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 0);
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- } else {
+ if (is_isa_board(thisboard)) {
if (dev->iobase)
release_region(dev->iobase, PC236_IO_SIZE);
+ } else if (is_pci_board(thisboard)) {
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ pci_dev_put(pcidev);
+ }
}
}
.num_names = ARRAY_SIZE(pc236_boards),
};
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC236_PCI)
+#if DO_PCI
static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) },
{0}
#define PC263_DRIVER_NAME "amplc_pc263"
+#define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA)
+#define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI)
+
/* PCI263 PCI configuration register information */
#define PCI_VENDOR_ID_AMPLICON 0x14dc
#define PCI_DEVICE_ID_AMPLICON_PCI263 0x000c
enum pc263_model model;
};
static const struct pc263_board pc263_boards[] = {
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA)
+#if DO_ISA
{
.name = "pc263",
.bustype = isa_bustype,
.model = pc263_model,
},
#endif
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI)
+#if DO_PCI
{
.name = "pci263",
.devid = PCI_DEVICE_ID_AMPLICON_PCI263,
#endif
};
+/* test if ISA supported and this is an ISA board */
+static inline bool is_isa_board(const struct pc263_board *board)
+{
+ return DO_ISA && board->bustype == isa_bustype;
+}
+
+/* test if PCI supported and this is a PCI board */
+static inline bool is_pci_board(const struct pc263_board *board)
+{
+ return DO_PCI && board->bustype == pci_bustype;
+}
+
/*
* This function looks for a board matching the supplied PCI device.
*/
unsigned int i;
for (i = 0; i < ARRAY_SIZE(pc263_boards); i++)
- if (pc263_boards[i].bustype == pci_bustype &&
+ if (is_pci_board(&pc263_boards[i]) &&
pci_dev->device == pc263_boards[i].devid)
return &pc263_boards[i];
return NULL;
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
char tmpbuf[40];
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) &&
- thisboard->bustype == isa_bustype)
+ if (is_isa_board(thisboard))
snprintf(tmpbuf, sizeof(tmpbuf), "(base %#lx) ", dev->iobase);
- else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) &&
- thisboard->bustype == pci_bustype)
+ else if (is_pci_board(thisboard))
snprintf(tmpbuf, sizeof(tmpbuf), "(pci %s) ",
pci_name(pcidev));
else
dev_info(dev->class_dev, PC263_DRIVER_NAME ": attach\n");
/* Process options and reserve resources according to bus type. */
- if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_ISA) &&
- thisboard->bustype == isa_bustype) {
+ if (is_isa_board(thisboard)) {
unsigned long iobase = it->options[0];
ret = pc263_request_region(dev, iobase, PC263_IO_SIZE);
if (ret < 0)
return ret;
return pc263_common_attach(dev, iobase);
- } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI) &&
- thisboard->bustype == pci_bustype) {
+ } else if (is_pci_board(thisboard)) {
struct pci_dev *pci_dev;
pci_dev = pc263_find_pci_dev(dev, it);
static int __devinit pc263_attach_pci(struct comedi_device *dev,
struct pci_dev *pci_dev)
{
- if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI))
+ if (!DO_PCI)
return -EINVAL;
dev_info(dev->class_dev, PC263_DRIVER_NAME ": attach pci %s\n",
static void pc263_detach(struct comedi_device *dev)
{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ const struct pc263_board *thisboard = comedi_board(dev);
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- } else {
+ if (is_isa_board(thisboard)) {
if (dev->iobase)
release_region(dev->iobase, PC263_IO_SIZE);
+ } else if (is_pci_board(thisboard)) {
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ pci_dev_put(pcidev);
+ }
}
}
.num_names = ARRAY_SIZE(pc263_boards),
};
-#if IS_ENABLED(CONFIG_COMEDI_AMPLC_PC263_PCI)
+#if DO_PCI
static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) },
{0}
The boards may be autocalibrated using the comedi_calibrate
utility.
-Configuration options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
+Configuration options: not applicable, uses PCI auto config
For commands, the scanned channels must be consecutive
(i.e. 4-5-6-7, 2-3-4,...), and must all have the same
return IRQ_HANDLED;
}
-static struct pci_dev *cb_pcidas_find_pci_device(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *cb_pcidas_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
const struct cb_pcidas_board *thisboard;
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
int i;
- for_each_pci_dev(pcidev) {
- /* is it not a computer boards card? */
- if (pcidev->vendor != PCI_VENDOR_ID_CB)
- continue;
- /* loop through cards supported by this driver */
- for (i = 0; i < ARRAY_SIZE(cb_pcidas_boards); i++) {
- thisboard = &cb_pcidas_boards[i];
- if (thisboard->device_id != pcidev->device)
- continue;
- /* was a particular bus/slot requested? */
- if (bus || slot) {
- /* are we on the wrong bus/slot? */
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot) {
- continue;
- }
- }
- dev_dbg(dev->class_dev,
- "Found %s on bus %i, slot %i\n",
- thisboard->name,
- pcidev->bus->number, PCI_SLOT(pcidev->devfn));
- dev->board_ptr = thisboard;
- return pcidev;
- }
+ for (i = 0; i < ARRAY_SIZE(cb_pcidas_boards); i++) {
+ thisboard = &cb_pcidas_boards[i];
+ if (thisboard->device_id == pcidev->device)
+ return thisboard;
}
- dev_err(dev->class_dev, "No supported card found\n");
return NULL;
}
-static int cb_pcidas_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int cb_pcidas_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
const struct cb_pcidas_board *thisboard;
struct cb_pcidas_private *devpriv;
- struct pci_dev *pcidev;
struct comedi_subdevice *s;
int i;
int ret;
- if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0)
- return -ENOMEM;
- devpriv = dev->private;
-
- pcidev = cb_pcidas_find_pci_device(dev, it);
- if (!pcidev)
- return -EIO;
comedi_set_hw_dev(dev, &pcidev->dev);
- thisboard = comedi_board(dev);
- if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
- dev_err(dev->class_dev,
- "Failed to enable PCI device and request regions\n");
- return -EIO;
- }
+ thisboard = cb_pcidas_find_boardinfo(dev, pcidev);
+ if (!thisboard)
+ return -ENODEV;
+ dev->board_ptr = thisboard;
+ dev->board_name = thisboard->name;
+
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
devpriv->s5933_config = pci_resource_start(pcidev, 0);
devpriv->control_status = pci_resource_start(pcidev, 1);
}
dev->irq = pcidev->irq;
- dev->board_name = thisboard->name;
-
ret = comedi_alloc_subdevices(dev, 7);
if (ret)
return ret;
outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
devpriv->s5933_config + AMCC_OP_REG_INTCSR);
- return 1;
+ dev_info(dev->class_dev, "%s: %s attached\n",
+ dev->driver->driver_name, dev->board_name);
+
+ return 0;
}
static void cb_pcidas_detach(struct comedi_device *dev)
if (pcidev) {
if (devpriv->s5933_config)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver cb_pcidas_driver = {
.driver_name = "cb_pcidas",
.module = THIS_MODULE,
- .attach = cb_pcidas_attach,
+ .attach_pci = cb_pcidas_attach_pci,
.detach = cb_pcidas_detach,
};
/* maximum number of ao channels for supported boards */
#define MAX_AO_CHANNELS 8
-/* PCI-DDA base addresses */
-#define DIGITALIO_BADRINDEX 2
- /* DIGITAL I/O is pci_dev->resource[2] */
-#define DIGITALIO_SIZE 8
- /* DIGITAL I/O uses 8 I/O port addresses */
-#define DAC_BADRINDEX 3
- /* DAC is pci_dev->resource[3] */
-
/* Digital I/O registers */
#define PORT1A 0 /* PORT 1A DATA */
},
};
-/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct cb_pcidda_board *)dev->board_ptr)
-
/*
* this structure is for data unique to this hardware driver. If
* several hardware drivers keep similar information in this structure,
u16 eeprom_data[EEPROM_SIZE]; /* software copy of board's eeprom */
};
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct cb_pcidda_private *)dev->private)
-
-/* static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */
-static int cb_pcidda_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-/* static int cb_pcidda_ai_cmd(struct comedi_device *dev, struct *comedi_subdevice *s);*/
-/* static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd); */
-/* static int cb_pcidda_ns_to_timer(unsigned int *ns,int *round); */
-
-static unsigned int cb_pcidda_serial_in(struct comedi_device *dev);
-static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
- unsigned int num_bits);
-static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
- unsigned int address);
-static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
- unsigned int range);
-
-static struct pci_dev *cb_pcidda_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
- int i;
-
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_CB)
- continue;
-
- for (i = 0; i < ARRAY_SIZE(cb_pcidda_boards); i++) {
- if (cb_pcidda_boards[i].device_id != pcidev->device)
- continue;
- dev->board_ptr = cb_pcidda_boards + i;
- return pcidev;
- }
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board.
- */
-static int cb_pcidda_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
- struct comedi_subdevice *s;
- int index;
- int ret;
-
-/*
- * Allocate the private structure area.
- */
- if (alloc_private(dev, sizeof(struct cb_pcidda_private)) < 0)
- return -ENOMEM;
-
- pcidev = cb_pcidda_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- /*
- * Enable PCI device and request regions.
- */
- if (comedi_pci_enable(pcidev, thisboard->name)) {
- dev_err(dev->class_dev,
- "cb_pcidda: failed to enable PCI device and request regions\n");
- return -EIO;
- }
-
-/*
- * Allocate the I/O ports.
- */
- devpriv->digitalio = pci_resource_start(pcidev, DIGITALIO_BADRINDEX);
- devpriv->dac = pci_resource_start(pcidev, DAC_BADRINDEX);
- dev->iobase = devpriv->dac;
-
-/*
- * Warn about the status of the driver.
- */
- if (thisboard->status == 2)
- printk
- ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. "
- "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. "
- "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
-
-/*
- * Initialize dev->board_name.
- */
- dev->board_name = thisboard->name;
-
- ret = comedi_alloc_subdevices(dev, 3);
- if (ret)
- return ret;
-
- s = dev->subdevices + 0;
- /* analog output subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = thisboard->ao_chans;
- s->maxdata = (1 << thisboard->ao_bits) - 1;
- s->range_table = thisboard->ranges;
- s->insn_write = cb_pcidda_ao_winsn;
-
- /* s->subdev_flags |= SDF_CMD_READ; */
- /* s->do_cmd = cb_pcidda_ai_cmd; */
- /* s->do_cmdtest = cb_pcidda_ai_cmdtest; */
-
- /* two 8255 digital io subdevices */
- s = dev->subdevices + 1;
- subdev_8255_init(dev, s, NULL, devpriv->digitalio);
- s = dev->subdevices + 2;
- subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
-
- dev_dbg(dev->class_dev, "eeprom:\n");
- for (index = 0; index < EEPROM_SIZE; index++) {
- devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
- dev_dbg(dev->class_dev, "%i:0x%x\n", index,
- devpriv->eeprom_data[index]);
- }
-
- /* set calibrations dacs */
- for (index = 0; index < thisboard->ao_chans; index++)
- cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]);
-
- return 1;
-}
-
-static void cb_pcidda_detach(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
- if (dev->subdevices) {
- subdev_8255_cleanup(dev, dev->subdevices + 1);
- subdev_8255_cleanup(dev, dev->subdevices + 2);
- }
-}
-
/*
* I will program this later... ;-)
*/
}
#endif
-static int cb_pcidda_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- unsigned int command;
- unsigned int channel, range;
-
- channel = CR_CHAN(insn->chanspec);
- range = CR_RANGE(insn->chanspec);
-
- /* adjust calibration dacs if range has changed */
- if (range != devpriv->ao_range[channel])
- cb_pcidda_calibrate(dev, channel, range);
-
- /* output channel configuration */
- command = NOSU | ENABLEDAC;
-
- /* output channel range */
- switch (range) {
- case 0:
- command |= BIP | RANGE10V;
- break;
- case 1:
- command |= BIP | RANGE5V;
- break;
- case 2:
- command |= BIP | RANGE2V5;
- break;
- case 3:
- command |= UNIP | RANGE10V;
- break;
- case 4:
- command |= UNIP | RANGE5V;
- break;
- case 5:
- command |= UNIP | RANGE2V5;
- break;
- }
-
- /* output channel specification */
- command |= channel << 2;
- outw(command, devpriv->dac + DACONTROL);
-
- /* write data */
- outw(data[0], devpriv->dac + DADATA + channel * 2);
-
- /* return the number of samples read/written */
- return 1;
-}
-
/* lowlevel read from eeprom */
static unsigned int cb_pcidda_serial_in(struct comedi_device *dev)
{
+ struct cb_pcidda_private *devpriv = dev->private;
unsigned int value = 0;
int i;
const int value_width = 16; /* number of bits wide values are */
static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
unsigned int num_bits)
{
+ struct cb_pcidda_private *devpriv = dev->private;
int i;
for (i = 1; i <= num_bits; i++) {
static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
unsigned int address)
{
+ struct cb_pcidda_private *devpriv = dev->private;
unsigned int i;
unsigned int cal2_bits;
unsigned int value;
unsigned int caldac, unsigned int channel,
unsigned int value)
{
+ struct cb_pcidda_private *devpriv = dev->private;
unsigned int cal2_bits;
unsigned int i;
/* caldacs use 3 bit channel specification */
static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
unsigned int range)
{
+ struct cb_pcidda_private *devpriv = dev->private;
unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
/* remember range so we can tell when we need to readjust calibration */
fine_gain_channel(channel), fine_gain);
}
+static int cb_pcidda_ao_winsn(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn, unsigned int *data)
+{
+ struct cb_pcidda_private *devpriv = dev->private;
+ unsigned int command;
+ unsigned int channel, range;
+
+ channel = CR_CHAN(insn->chanspec);
+ range = CR_RANGE(insn->chanspec);
+
+ /* adjust calibration dacs if range has changed */
+ if (range != devpriv->ao_range[channel])
+ cb_pcidda_calibrate(dev, channel, range);
+
+ /* output channel configuration */
+ command = NOSU | ENABLEDAC;
+
+ /* output channel range */
+ switch (range) {
+ case 0:
+ command |= BIP | RANGE10V;
+ break;
+ case 1:
+ command |= BIP | RANGE5V;
+ break;
+ case 2:
+ command |= BIP | RANGE2V5;
+ break;
+ case 3:
+ command |= UNIP | RANGE10V;
+ break;
+ case 4:
+ command |= UNIP | RANGE5V;
+ break;
+ case 5:
+ command |= UNIP | RANGE2V5;
+ break;
+ }
+
+ /* output channel specification */
+ command |= channel << 2;
+ outw(command, devpriv->dac + DACONTROL);
+
+ /* write data */
+ outw(data[0], devpriv->dac + DADATA + channel * 2);
+
+ /* return the number of samples read/written */
+ return 1;
+}
+
+static const void *cb_pcidda_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct cb_pcidda_board *thisboard;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cb_pcidda_boards); i++) {
+ thisboard = &cb_pcidda_boards[i];
+ if (thisboard->device_id != pcidev->device)
+ return thisboard;
+ }
+ return NULL;
+}
+
+static int cb_pcidda_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct cb_pcidda_board *thisboard;
+ struct cb_pcidda_private *devpriv;
+ struct comedi_subdevice *s;
+ int index;
+ int ret;
+
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ thisboard = cb_pcidda_find_boardinfo(dev, pcidev);
+ if (!pcidev)
+ return -ENODEV;
+ dev->board_ptr = thisboard;
+ dev->board_name = thisboard->name;
+
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+
+ devpriv->digitalio = pci_resource_start(pcidev, 2);
+ devpriv->dac = pci_resource_start(pcidev, 3);
+ dev->iobase = devpriv->dac;
+
+ if (thisboard->status == 2)
+ printk
+ ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. "
+ "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. "
+ "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
+
+ ret = comedi_alloc_subdevices(dev, 3);
+ if (ret)
+ return ret;
+
+ s = dev->subdevices + 0;
+ /* analog output subdevice */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = thisboard->ao_chans;
+ s->maxdata = (1 << thisboard->ao_bits) - 1;
+ s->range_table = thisboard->ranges;
+ s->insn_write = cb_pcidda_ao_winsn;
+
+ /* s->subdev_flags |= SDF_CMD_READ; */
+ /* s->do_cmd = cb_pcidda_ai_cmd; */
+ /* s->do_cmdtest = cb_pcidda_ai_cmdtest; */
+
+ /* two 8255 digital io subdevices */
+ s = dev->subdevices + 1;
+ subdev_8255_init(dev, s, NULL, devpriv->digitalio);
+ s = dev->subdevices + 2;
+ subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
+
+ dev_dbg(dev->class_dev, "eeprom:\n");
+ for (index = 0; index < EEPROM_SIZE; index++) {
+ devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
+ dev_dbg(dev->class_dev, "%i:0x%x\n", index,
+ devpriv->eeprom_data[index]);
+ }
+
+ /* set calibrations dacs */
+ for (index = 0; index < thisboard->ao_chans; index++)
+ cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]);
+
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+
+ return 0;
+}
+
+static void cb_pcidda_detach(struct comedi_device *dev)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+ if (dev->subdevices) {
+ subdev_8255_cleanup(dev, dev->subdevices + 1);
+ subdev_8255_cleanup(dev, dev->subdevices + 2);
+ }
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ }
+}
+
static struct comedi_driver cb_pcidda_driver = {
.driver_name = "cb_pcidda",
.module = THIS_MODULE,
- .attach = cb_pcidda_attach,
+ .attach_pci = cb_pcidda_attach_pci,
.detach = cb_pcidda_detach,
};
This driver has been modified from skel.c of comedi-0.7.70.
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first available PCI device will
- be used.
-
-Passing a zero for an option is the same as leaving it unspecified.
+Configuration Options: not applicable, uses PCI auto config
*/
/*------------------------------ HEADER FILES ---------------------------------*/
},
};
-/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct pcidio_board *)dev->board_ptr)
-
-static struct pci_dev *pcidio_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *pcidio_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
+ const struct pcidio_board *board;
int i;
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_CB)
- continue;
- for (i = 0; i < ARRAY_SIZE(pcidio_boards); i++) {
- if (pcidio_boards[i].dev_id != pcidev->device)
- continue;
-
- dev->board_ptr = pcidio_boards + i;
- return pcidev;
- }
+ for (i = 0; i < ARRAY_SIZE(pcidio_boards); i++) {
+ board = &pcidio_boards[i];
+ if (board->dev_id == pcidev->device)
+ return board;
}
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
return NULL;
}
-static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int pcidio_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev;
+ const struct pcidio_board *board;
+ struct comedi_subdevice *s;
int i;
int ret;
- pcidev = pcidio_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
comedi_set_hw_dev(dev, &pcidev->dev);
-/*
- * Initialize dev->board_name. Note that we can use the "thisboard"
- * macro now, since we just initialized it in the last line.
- */
- dev->board_name = thisboard->name;
-
- if (comedi_pci_enable(pcidev, thisboard->name))
- return -EIO;
+ board = pcidio_find_boardinfo(dev, pcidev);
+ if (!board)
+ return -ENODEV;
+ dev->board_ptr = board;
+ dev->board_name = board->name;
- dev->iobase = pci_resource_start(pcidev, thisboard->dioregs_badrindex);
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+ dev->iobase = pci_resource_start(pcidev, board->dioregs_badrindex);
- ret = comedi_alloc_subdevices(dev, thisboard->n_8255);
+ ret = comedi_alloc_subdevices(dev, board->n_8255);
if (ret)
return ret;
- for (i = 0; i < thisboard->n_8255; i++) {
- subdev_8255_init(dev, dev->subdevices + i,
- NULL, dev->iobase + i * 4);
- dev_dbg(dev->class_dev, "subdev %d: base = 0x%lx\n", i,
- dev->iobase + i * 4);
+ for (i = 0; i < board->n_8255; i++) {
+ s = dev->subdevices + i;
+ ret = subdev_8255_init(dev, s, NULL, dev->iobase + i * 4);
+ if (ret)
+ return ret;
}
- return 1;
+ dev_info(dev->class_dev, "%s attached (%d digital i/o channels)\n",
+ dev->board_name, board->n_8255 * 24);
+
+ return 0;
}
static void pcidio_detach(struct comedi_device *dev)
{
+ const struct pcidio_board *board = comedi_board(dev);
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ struct comedi_subdevice *s;
+ int i;
+ if (dev->subdevices) {
+ for (i = 0; i < board->n_8255; i++) {
+ s = dev->subdevices + i;
+ subdev_8255_cleanup(dev, s);
+ }
+ }
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
- if (dev->subdevices) {
- int i;
- for (i = 0; i < thisboard->n_8255; i++)
- subdev_8255_cleanup(dev, dev->subdevices + i);
}
}
static struct comedi_driver cb_pcidio_driver = {
.driver_name = "cb_pcidio",
.module = THIS_MODULE,
- .attach = pcidio_attach,
+ .attach_pci = pcidio_attach_pci,
.detach = pcidio_detach,
};
},
};
-/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct cb_pcimdas_board *)dev->board_ptr)
-
/*
* this structure is for data unique to this hardware driver. If
* several hardware drivers keep similar information in this structure,
unsigned int ao_readback[2];
};
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct cb_pcimdas_private *)dev->private)
-
-static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int cb_pcimdas_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-
-static struct pci_dev *cb_pcimdas_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
- int i;
-
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
- continue;
-
- for (i = 0; i < ARRAY_SIZE(cb_pcimdas_boards); i++) {
- if (cb_pcimdas_boards[i].device_id != pcidev->device)
- continue;
-
- dev->board_ptr = cb_pcimdas_boards + i;
- return pcidev;
- }
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
-static int cb_pcimdas_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
- struct comedi_subdevice *s;
- unsigned long iobase_8255;
- int ret;
-
-/*
- * Allocate the private structure area.
- */
- if (alloc_private(dev, sizeof(struct cb_pcimdas_private)) < 0)
- return -ENOMEM;
-
- pcidev = cb_pcimdas_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- /* Warn about non-tested features */
- switch (thisboard->device_id) {
- case 0x56:
- break;
- default:
- dev_dbg(dev->class_dev, "THIS CARD IS UNSUPPORTED.\n");
- dev_dbg(dev->class_dev,
- "PLEASE REPORT USAGE TO <mocelet@sucs.org>\n");
- }
-
- if (comedi_pci_enable(pcidev, "cb_pcimdas")) {
- dev_err(dev->class_dev,
- "Failed to enable PCI device and request regions\n");
- return -EIO;
- }
-
- dev->iobase = pci_resource_start(pcidev, 2);
- devpriv->BADR3 = pci_resource_start(pcidev, 3);
- iobase_8255 = pci_resource_start(pcidev, 4);
-
-/* Dont support IRQ yet */
-/* get irq */
-/* if(request_irq(pcidev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev )) */
-/* { */
-/* printk(" unable to allocate irq %u\n", pcidev->irq); */
-/* return -EINVAL; */
-/* } */
-/* dev->irq = pcidev->irq; */
-
- /* Initialize dev->board_name */
- dev->board_name = thisboard->name;
-
- ret = comedi_alloc_subdevices(dev, 3);
- if (ret)
- return ret;
-
- s = dev->subdevices + 0;
- /* dev->read_subdev=s; */
- /* analog input subdevice */
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND;
- s->n_chan = thisboard->ai_se_chans;
- s->maxdata = (1 << thisboard->ai_bits) - 1;
- s->range_table = &range_unknown;
- s->len_chanlist = 1; /* This is the maximum chanlist length that */
- /* the board can handle */
- s->insn_read = cb_pcimdas_ai_rinsn;
-
- s = dev->subdevices + 1;
- /* analog output subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = thisboard->ao_nchan;
- s->maxdata = 1 << thisboard->ao_bits;
- /* ranges are hardware settable, but not software readable. */
- s->range_table = &range_unknown;
- s->insn_write = &cb_pcimdas_ao_winsn;
- s->insn_read = &cb_pcimdas_ao_rinsn;
-
- s = dev->subdevices + 2;
- /* digital i/o subdevice */
- if (thisboard->has_dio)
- subdev_8255_init(dev, s, NULL, iobase_8255);
- else
- s->type = COMEDI_SUBD_UNUSED;
-
- return 1;
-}
-
-static void cb_pcimdas_detach(struct comedi_device *dev)
-{
- struct pci_dev *pcidev = comedi_to_pci_dev(dev);
-
- if (dev->irq)
- free_irq(dev->irq, dev);
- if (pcidev) {
- if (dev->iobase)
- comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
- }
-}
-
/*
* "instructions" read/write data in "one-shot" or "software-triggered"
* mode.
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ const struct cb_pcimdas_board *thisboard = comedi_board(dev);
+ struct cb_pcimdas_private *devpriv = dev->private;
int n, i;
unsigned int d;
unsigned int busy;
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct cb_pcimdas_private *devpriv = dev->private;
int i;
int chan = CR_CHAN(insn->chanspec);
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct cb_pcimdas_private *devpriv = dev->private;
int i;
int chan = CR_CHAN(insn->chanspec);
return i;
}
+static const void *cb_pcimdas_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct cb_pcimdas_board *thisboard;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cb_pcimdas_boards); i++) {
+ thisboard = &cb_pcimdas_boards[i];
+ if (thisboard->device_id == pcidev->device)
+ return thisboard;
+ }
+ return NULL;
+}
+
+static int cb_pcimdas_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
+{
+ const struct cb_pcimdas_board *thisboard;
+ struct cb_pcimdas_private *devpriv;
+ struct comedi_subdevice *s;
+ unsigned long iobase_8255;
+ int ret;
+
+ comedi_set_hw_dev(dev, &pcidev->dev);
+
+ thisboard = cb_pcimdas_find_boardinfo(dev, pcidev);
+ if (!thisboard)
+ return -ENODEV;
+ dev->board_ptr = thisboard;
+ dev->board_name = thisboard->name;
+
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
+
+ /* Warn about non-tested features */
+ switch (thisboard->device_id) {
+ case 0x56:
+ break;
+ default:
+ dev_dbg(dev->class_dev, "THIS CARD IS UNSUPPORTED.\n");
+ dev_dbg(dev->class_dev,
+ "PLEASE REPORT USAGE TO <mocelet@sucs.org>\n");
+ }
+
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+
+ dev->iobase = pci_resource_start(pcidev, 2);
+ devpriv->BADR3 = pci_resource_start(pcidev, 3);
+ iobase_8255 = pci_resource_start(pcidev, 4);
+
+/* Dont support IRQ yet */
+/* get irq */
+/* if(request_irq(pcidev->irq, cb_pcimdas_interrupt, IRQF_SHARED, "cb_pcimdas", dev )) */
+/* { */
+/* printk(" unable to allocate irq %u\n", pcidev->irq); */
+/* return -EINVAL; */
+/* } */
+/* dev->irq = pcidev->irq; */
+
+ ret = comedi_alloc_subdevices(dev, 3);
+ if (ret)
+ return ret;
+
+ s = dev->subdevices + 0;
+ /* dev->read_subdev=s; */
+ /* analog input subdevice */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ s->n_chan = thisboard->ai_se_chans;
+ s->maxdata = (1 << thisboard->ai_bits) - 1;
+ s->range_table = &range_unknown;
+ s->len_chanlist = 1; /* This is the maximum chanlist length that */
+ /* the board can handle */
+ s->insn_read = cb_pcimdas_ai_rinsn;
+
+ s = dev->subdevices + 1;
+ /* analog output subdevice */
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = thisboard->ao_nchan;
+ s->maxdata = 1 << thisboard->ao_bits;
+ /* ranges are hardware settable, but not software readable. */
+ s->range_table = &range_unknown;
+ s->insn_write = &cb_pcimdas_ao_winsn;
+ s->insn_read = &cb_pcimdas_ao_rinsn;
+
+ s = dev->subdevices + 2;
+ /* digital i/o subdevice */
+ if (thisboard->has_dio)
+ subdev_8255_init(dev, s, NULL, iobase_8255);
+ else
+ s->type = COMEDI_SUBD_UNUSED;
+
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
+
+ return 0;
+}
+
+static void cb_pcimdas_detach(struct comedi_device *dev)
+{
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+
+ if (dev->irq)
+ free_irq(dev->irq, dev);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
+ }
+}
+
static struct comedi_driver cb_pcimdas_driver = {
.driver_name = "cb_pcimdas",
.module = THIS_MODULE,
- .attach = cb_pcimdas_attach,
+ .attach_pci = cb_pcimdas_attach_pci,
.detach = cb_pcimdas_detach,
};
then issue one comedi_data_read() on any channel on the AO subdevice
to initiate the simultaneous XFER.
-Configuration Options:
- [0] PCI bus (optional)
- [1] PCI slot (optional)
- [2] analog output range jumper setting
- 0 == +/- 5 V
- 1 == +/- 10 V
+Configuration Options: not applicable, uses PCI auto config
*/
/*
#define PCI_ID_PCIM_DDA06_16 0x0053
/*
- * This is straight from skel.c -- I did this in case this source file
- * will someday support more than 1 board...
+ * Register map, 8-bit access only
*/
-struct board_struct {
- const char *name;
- unsigned short device_id;
- int ao_chans;
- int ao_bits;
- int dio_chans;
- int dio_method;
- /* how many bytes into the BADR are the DIO ports */
- int dio_offset;
- int regs_badrindex; /* IO Region for the control, analog output,
- and DIO registers */
- int reg_sz; /* number of bytes of registers in io region */
-};
+#define PCIMDDA_DA_CHAN(x) (0x00 + (x) * 2)
+#define PCIMDDA_8255_BASE_REG 0x0c
-enum DIO_METHODS {
- DIO_NONE = 0,
- DIO_8255,
- DIO_INTERNAL /* unimplemented */
-};
+#define MAX_AO_READBACK_CHANNELS 6
-static const struct board_struct boards[] = {
- {
- .name = "cb_pcimdda06-16",
- .device_id = PCI_ID_PCIM_DDA06_16,
- .ao_chans = 6,
- .ao_bits = 16,
- .dio_chans = 24,
- .dio_method = DIO_8255,
- .dio_offset = 12,
- .regs_badrindex = 3,
- .reg_sz = 16,
- }
+struct cb_pcimdda_private {
+ unsigned int ao_readback[MAX_AO_READBACK_CHANNELS];
};
-/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct board_struct *)dev->board_ptr)
-
-#define REG_SZ (thisboard->reg_sz)
-#define REGS_BADRINDEX (thisboard->regs_badrindex)
-
-/*
- * this structure is for data unique to this hardware driver. If
- * several hardware drivers keep similar information in this structure,
- * feel free to suggest moving the variable to the struct comedi_device
- * struct.
- */
-struct board_private_struct {
- unsigned long registers; /* set by probe */
- unsigned long dio_registers;
- char attached_to_8255; /* boolean */
- /* would be useful for a PCI device */
- struct pci_dev *pci_dev;
-
-#define MAX_AO_READBACK_CHANNELS 6
- /* Used for AO readback */
- unsigned int ao_readback[MAX_AO_READBACK_CHANNELS];
+static int cb_pcimdda_ao_winsn(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ struct cb_pcimdda_private *devpriv = dev->private;
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned long offset = dev->iobase + PCIMDDA_DA_CHAN(chan);
+ unsigned int val = 0;
+ int i;
-};
+ for (i = 0; i < insn->n; i++) {
+ val = data[i];
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct board_private_struct *)dev->private)
+ /*
+ * Write the LSB then MSB.
+ *
+ * If the simultaneous xfer mode is selected by the
+ * jumper on the card, a read instruction is needed
+ * in order to initiate the simultaneous transfer.
+ * Otherwise, the DAC will be updated when the MSB
+ * is written.
+ */
+ outb(val & 0x00ff, offset);
+ outb((val >> 8) & 0x00ff, offset + 1);
+ }
-static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
-static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
+ /* Cache the last value for readback */
+ devpriv->ao_readback[chan] = val;
-/*---------------------------------------------------------------------------
- HELPER FUNCTION DECLARATIONS
------------------------------------------------------------------------------*/
+ return insn->n;
+}
-/* returns a maxdata value for a given n_bits */
-static inline unsigned int figure_out_maxdata(int bits)
+static int cb_pcimdda_ao_rinsn(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- return ((unsigned int)1 << bits) - 1;
-}
+ struct cb_pcimdda_private *devpriv = dev->private;
+ int chan = CR_CHAN(insn->chanspec);
+ unsigned long offset = dev->iobase + PCIMDDA_DA_CHAN(chan);
+ int i;
-/*
- * Probes for a supported device.
- *
- * Prerequisite: private be allocated already inside dev
- *
- * If the device is found, it returns 0 and has the following side effects:
- *
- * o assigns a struct pci_dev * to dev->private->pci_dev
- * o assigns a struct board * to dev->board_ptr
- * o sets dev->private->registers
- * o sets dev->private->dio_registers
- *
- * Otherwise, returns a -errno on error
- */
-static int probe(struct comedi_device *dev, const struct comedi_devconfig *it);
+ for (i = 0; i < insn->n; i++) {
+ /* Initiate the simultaneous transfer */
+ inw(offset);
+
+ data[i] = devpriv->ao_readback[chan];
+ }
-/*---------------------------------------------------------------------------
- FUNCTION DEFINITIONS
------------------------------------------------------------------------------*/
+ return insn->n;
+}
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
-static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int cb_pcimdda_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
+ struct cb_pcimdda_private *devpriv;
struct comedi_subdevice *s;
- int err;
+ int ret;
-/*
- * Allocate the private structure area. alloc_private() is a
- * convenient macro defined in comedidev.h.
- * if this function fails (returns negative) then the private area is
- * kfree'd by comedi
- */
- if (alloc_private(dev, sizeof(struct board_private_struct)) < 0)
- return -ENOMEM;
+ comedi_set_hw_dev(dev, &pcidev->dev);
+ dev->board_name = dev->driver->driver_name;
-/*
- * If you can probe the device to determine what device in a series
- * it is, this is the place to do it. Otherwise, dev->board_ptr
- * should already be initialized.
- */
- err = probe(dev, it);
- if (err)
- return err;
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
-/* Output some info */
- printk("comedi%d: %s: ", dev->minor, thisboard->name);
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+ dev->iobase = pci_resource_start(pcidev, 3);
-/*
- * Initialize dev->board_name. Note that we can use the "thisboard"
- * macro now, since we just initialized it in the last line.
- */
- dev->board_name = thisboard->name;
-
- err = comedi_alloc_subdevices(dev, 2);
- if (err)
- return err;
+ ret = comedi_alloc_subdevices(dev, 2);
+ if (ret)
+ return ret;
s = dev->subdevices + 0;
-
/* analog output subdevice */
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
- s->n_chan = thisboard->ao_chans;
- s->maxdata = figure_out_maxdata(thisboard->ao_bits);
- /* this is hard-coded here */
- if (it->options[2])
- s->range_table = &range_bipolar10;
- else
- s->range_table = &range_bipolar5;
- s->insn_write = &ao_winsn;
- s->insn_read = &ao_rinsn;
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
+ s->n_chan = 6;
+ s->maxdata = 0xffff;
+ s->range_table = &range_bipolar5;
+ s->insn_write = cb_pcimdda_ao_winsn;
+ s->insn_read = cb_pcimdda_ao_rinsn;
s = dev->subdevices + 1;
/* digital i/o subdevice */
- if (thisboard->dio_chans) {
- switch (thisboard->dio_method) {
- case DIO_8255:
- /*
- * this is a straight 8255, so register us with
- * the 8255 driver
- */
- subdev_8255_init(dev, s, NULL, devpriv->dio_registers);
- devpriv->attached_to_8255 = 1;
- break;
- case DIO_INTERNAL:
- default:
- printk("DIO_INTERNAL not implemented yet!\n");
- return -ENXIO;
- break;
- }
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
+ ret = subdev_8255_init(dev, s, NULL,
+ dev->iobase + PCIMDDA_8255_BASE_REG);
+ if (ret)
+ return ret;
- printk("attached\n");
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
return 1;
}
-static void detach(struct comedi_device *dev)
-{
- if (devpriv) {
- if (dev->subdevices && devpriv->attached_to_8255) {
- subdev_8255_cleanup(dev, dev->subdevices + 2);
- devpriv->attached_to_8255 = 0;
- }
- if (devpriv->pci_dev) {
- if (devpriv->registers)
- comedi_pci_disable(devpriv->pci_dev);
- pci_dev_put(devpriv->pci_dev);
- }
- }
-}
-
-static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static void cb_pcimdda_detach(struct comedi_device *dev)
{
- int i;
- int chan = CR_CHAN(insn->chanspec);
- unsigned long offset = devpriv->registers + chan * 2;
+ struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- /* Writing a list of values to an AO channel is probably not
- * very useful, but that's how the interface is defined. */
- for (i = 0; i < insn->n; i++) {
- /* first, load the low byte */
- outb((char)(data[i] & 0x00ff), offset);
- /* next, write the high byte -- only after this is written is
- the channel voltage updated in the DAC, unless
- we're in simultaneous xfer mode (jumper on card)
- then a rinsn is necessary to actually update the DAC --
- see ao_rinsn() below... */
- outb((char)(data[i] >> 8 & 0x00ff), offset + 1);
-
- /* for testing only.. the actual rinsn SHOULD do an inw!
- (see the stuff about simultaneous XFER mode on this board) */
- devpriv->ao_readback[chan] = data[i];
+ if (dev->subdevices)
+ subdev_8255_cleanup(dev, dev->subdevices + 1);
+ if (pcidev) {
+ if (dev->iobase)
+ comedi_pci_disable(pcidev);
}
-
- /* return the number of samples read/written */
- return i;
-}
-
-/* AO subdevices should have a read insn as well as a write insn.
-
- Usually this means copying a value stored in devpriv->ao_readback.
- However, since this board has this jumper setting called "Simultaneous
- Xfer mode" (off by default), we will support it. Simultaneaous xfer
- mode is accomplished by loading ALL the values you want for AO in all the
- channels, then READing off one of the AO registers to initiate the
- instantaneous simultaneous update of all DAC outputs, which makes
- all AO channels update simultaneously. This is useful for some control
- applications, I would imagine.
-*/
-static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- int i;
- int chan = CR_CHAN(insn->chanspec);
-
- for (i = 0; i < insn->n; i++) {
- inw(devpriv->registers + chan * 2);
- /*
- * should I set data[i] to the result of the actual read
- * on the register or the cached unsigned int in
- * devpriv->ao_readback[]?
- */
- data[i] = devpriv->ao_readback[chan];
- }
-
- return i;
-}
-
-/*---------------------------------------------------------------------------
- HELPER FUNCTION DEFINITIONS
------------------------------------------------------------------------------*/
-
-/*
- * Probes for a supported device.
- *
- * Prerequisite: private be allocated already inside dev
- *
- * If the device is found, it returns 0 and has the following side effects:
- *
- * o assigns a struct pci_dev * to dev->private->pci_dev
- * o assigns a struct board * to dev->board_ptr
- * o sets dev->private->registers
- * o sets dev->private->dio_registers
- *
- * Otherwise, returns a -errno on error
- */
-static int probe(struct comedi_device *dev, const struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int index;
- unsigned long registers;
-
- for_each_pci_dev(pcidev) {
- /* is it not a computer boards card? */
- if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
- continue;
- /* loop through cards supported by this driver */
- for (index = 0; index < ARRAY_SIZE(boards); index++) {
- if (boards[index].device_id != pcidev->device)
- continue;
- /* was a particular bus/slot requested? */
- if (it->options[0] || it->options[1]) {
- /* are we on the wrong bus/slot? */
- if (pcidev->bus->number != it->options[0] ||
- PCI_SLOT(pcidev->devfn) != it->options[1]) {
- continue;
- }
- }
- /* found ! */
-
- devpriv->pci_dev = pcidev;
- dev->board_ptr = boards + index;
- if (comedi_pci_enable(pcidev, thisboard->name)) {
- printk
- ("cb_pcimdda: Failed to enable PCI device and request regions\n");
- return -EIO;
- }
- registers =
- pci_resource_start(devpriv->pci_dev,
- REGS_BADRINDEX);
- devpriv->registers = registers;
- devpriv->dio_registers
- = devpriv->registers + thisboard->dio_offset;
- return 0;
- }
- }
-
- printk("cb_pcimdda: No supported ComputerBoards/MeasurementComputing "
- "card found at the requested position\n");
- return -ENODEV;
}
static struct comedi_driver cb_pcimdda_driver = {
.driver_name = "cb_pcimdda",
.module = THIS_MODULE,
- .attach = attach,
- .detach = detach,
+ .attach_pci = cb_pcimdda_attach_pci,
+ .detach = cb_pcimdda_detach,
};
static int __devinit cb_pcimdda_pci_probe(struct pci_dev *dev,
/* The maxiumum number of channels per subdevice. */
#define MAX_CHANS 256
-#define MODULE_NAME "comedi_bond"
-#ifndef STR
-# define STR1(x) #x
-# define STR(x) STR1(x)
-#endif
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "If true, print extra cryptic debugging output useful"
- "only to developers.");
-
-#define LOG_MSG(x...) printk(KERN_INFO MODULE_NAME": "x)
-#define DEBUG(x...) \
- do { \
- if (debug) \
- printk(KERN_DEBUG MODULE_NAME": DEBUG: "x); \
- } while (0)
-#define WARNING(x...) printk(KERN_WARNING MODULE_NAME ": WARNING: "x)
-#define ERROR(x...) printk(KERN_ERR MODULE_NAME ": INTERNAL ERROR: "x)
-
-/*
- * Board descriptions for two imaginary boards. Describing the
- * boards in this way is optional, and completely driver-dependent.
- * Some drivers use arrays such as this, other do not.
- */
-struct BondingBoard {
- const char *name;
-};
-
-/*
- * Useful for shorthand access to the particular board structure
- */
-#define thisboard ((const struct BondingBoard *)dev->board_ptr)
-
struct BondedDevice {
struct comedi_device *dev;
unsigned minor;
/* this structure is for data unique to this hardware driver. If
several hardware drivers keep similar information in this structure,
feel free to suggest moving the variable to the struct comedi_device struct. */
-struct Private {
+struct comedi_bond_private {
# define MAX_BOARD_NAME 256
char name[MAX_BOARD_NAME];
struct BondedDevice **devs;
unsigned nchans;
};
-/*
- * most drivers define the following macro to make it easy to
- * access the private structure.
- */
-#define devpriv ((struct Private *)dev->private)
-
/* DIO devices are slightly special. Although it is possible to
* implement the insn_read/insn_write interface, it is much more
* useful to applications if you implement the insn_bits interface.
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct comedi_bond_private *devpriv = dev->private;
#define LSAMPL_BITS (sizeof(unsigned int)*8)
unsigned nchans = LSAMPL_BITS, num_done = 0, i;
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct comedi_bond_private *devpriv = dev->private;
int chan = CR_CHAN(insn->chanspec), ret, io_bits = s->io_bits;
unsigned int io;
struct BondedDevice *bdev;
static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
{
+ struct comedi_bond_private *devpriv = dev->private;
int i;
struct comedi_device *devs_opened[COMEDI_NUM_BOARD_MINORS];
struct BondedDevice *bdev = NULL;
if (minor < 0 || minor >= COMEDI_NUM_BOARD_MINORS) {
- ERROR("Minor %d is invalid!\n", minor);
+ dev_err(dev->class_dev,
+ "Minor %d is invalid!\n", minor);
return 0;
}
if (minor == dev->minor) {
- ERROR("Cannot bond this driver to itself!\n");
+ dev_err(dev->class_dev,
+ "Cannot bond this driver to itself!\n");
return 0;
}
if (devs_opened[minor]) {
- ERROR("Minor %d specified more than once!\n", minor);
+ dev_err(dev->class_dev,
+ "Minor %d specified more than once!\n", minor);
return 0;
}
d = devs_opened[minor] = comedi_open(file);
if (!d) {
- ERROR("Minor %u could not be opened\n", minor);
+ dev_err(dev->class_dev,
+ "Minor %u could not be opened\n", minor);
return 0;
}
sdev + 1)) > -1) {
nchans = comedi_get_n_channels(d, sdev);
if (nchans <= 0) {
- ERROR("comedi_get_n_channels() returned %d "
- "on minor %u subdev %d!\n",
- nchans, minor, sdev);
+ dev_err(dev->class_dev,
+ "comedi_get_n_channels() returned %d on minor %u subdev %d!\n",
+ nchans, minor, sdev);
return 0;
}
bdev = kmalloc(sizeof(*bdev), GFP_KERNEL);
if (!bdev) {
- ERROR("Out of memory.\n");
+ dev_err(dev->class_dev, "Out of memory\n");
return 0;
}
bdev->dev = d;
Realloc(devpriv->devs,
++devpriv->ndevs * sizeof(bdev), tmp);
if (!devpriv->devs) {
- ERROR("Could not allocate memory. "
- "Out of memory?");
+ dev_err(dev->class_dev,
+ "Could not allocate memory. Out of memory?\n");
return 0;
}
}
if (!devpriv->nchans) {
- ERROR("No channels found!\n");
+ dev_err(dev->class_dev, "No channels found!\n");
return 0;
}
static int bonding_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
+ struct comedi_bond_private *devpriv;
struct comedi_subdevice *s;
int ret;
- LOG_MSG("comedi%d\n", dev->minor);
-
- /*
- * Allocate the private structure area. alloc_private() is a
- * convenient macro defined in comedidev.h.
- */
- if (alloc_private(dev, sizeof(struct Private)) < 0)
- return -ENOMEM;
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
/*
- * Setup our bonding from config params.. sets up our Private struct..
+ * Setup our bonding from config params.. sets up our private struct..
*/
if (!doDevConfig(dev, it))
return -EINVAL;
- /*
- * Initialize dev->board_name. Note that we can use the "thisboard"
- * macro now, since we just initialized it in the last line.
- */
dev->board_name = devpriv->name;
ret = comedi_alloc_subdevices(dev, 1);
s->insn_bits = bonding_dio_insn_bits;
s->insn_config = bonding_dio_insn_config;
- LOG_MSG("attached with %u DIO channels coming from %u different "
- "subdevices all bonded together. "
- "John Lennon would be proud!\n",
+ dev_info(dev->class_dev,
+ "%s: %s attached, %u channels from %u devices\n",
+ dev->driver->driver_name, dev->board_name,
devpriv->nchans, devpriv->ndevs);
return 1;
static void bonding_detach(struct comedi_device *dev)
{
+ struct comedi_bond_private *devpriv = dev->private;
unsigned long devs_closed = 0;
if (devpriv) {
}
}
-static const struct BondingBoard bondingBoards[] = {
- {
- .name = "comedi_bond",
- },
-};
-
static struct comedi_driver bonding_driver = {
.driver_name = "comedi_bond",
.module = THIS_MODULE,
.attach = bonding_attach,
.detach = bonding_detach,
- .board_name = &bondingBoards[0].name,
- .offset = sizeof(struct BondingBoard),
- .num_names = ARRAY_SIZE(bondingBoards),
};
module_comedi_driver(bonding_driver);
MODULE_AUTHOR("Calin A. Culianu");
-MODULE_DESCRIPTION(MODULE_NAME "A driver for COMEDI to bond multiple COMEDI "
+MODULE_DESCRIPTION("comedi_bond: A driver for COMEDI to bond multiple COMEDI "
"devices together as one. In the words of John Lennon: "
"'And the world will live as one...'");
MODULE_LICENSE("GPL");
unsigned int c_data;
int enable_irq;
};
-#define devpriv ((struct parport_private *)(dev->private))
static int parport_insn_a(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct parport_private *devpriv = dev->private;
+
if (data[0]) {
devpriv->a_data &= ~data[0];
devpriv->a_data |= (data[0] & data[1]);
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct parport_private *devpriv = dev->private;
+
if (data[0]) {
s->io_bits = 0xff;
devpriv->c_data &= ~(1 << 5);
static int parport_insn_c(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct parport_private *devpriv = dev->private;
+
data[0] &= 0x0f;
if (data[0]) {
devpriv->c_data &= ~data[0];
static int parport_intr_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{
+ struct parport_private *devpriv = dev->private;
+
devpriv->c_data |= 0x10;
outb(devpriv->c_data, dev->iobase + PARPORT_C);
static int parport_intr_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- printk(KERN_DEBUG "parport_intr_cancel()\n");
+ struct parport_private *devpriv = dev->private;
devpriv->c_data &= ~0x10;
outb(devpriv->c_data, dev->iobase + PARPORT_C);
static irqreturn_t parport_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
+ struct parport_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->subdevices + 3;
- if (!devpriv->enable_irq) {
- printk(KERN_ERR "comedi_parport: bogus irq, ignored\n");
+ if (!devpriv->enable_irq)
return IRQ_NONE;
- }
comedi_buf_put(s->async, 0);
s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
static int parport_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
+ struct parport_private *devpriv;
int ret;
unsigned int irq;
unsigned long iobase;
struct comedi_subdevice *s;
+ dev->board_name = dev->driver->driver_name;
+
iobase = it->options[0];
- printk(KERN_INFO "comedi%d: parport: 0x%04lx ", dev->minor, iobase);
- if (!request_region(iobase, PARPORT_SIZE, "parport (comedi)")) {
- printk(KERN_ERR "I/O port conflict\n");
+ if (!request_region(iobase, PARPORT_SIZE, dev->board_name)) {
+ dev_err(dev->class_dev, "I/O port conflict\n");
return -EIO;
}
dev->iobase = iobase;
irq = it->options[1];
if (irq) {
- printk(KERN_INFO " irq=%u", irq);
- ret = request_irq(irq, parport_interrupt, 0, "comedi_parport",
+ ret = request_irq(irq, parport_interrupt, 0, dev->board_name,
dev);
if (ret < 0) {
- printk(KERN_ERR " irq not available\n");
+ dev_err(dev->class_dev, "irq not available\n");
return -EINVAL;
}
dev->irq = irq;
}
- dev->board_name = "parport";
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
- ret = alloc_private(dev, sizeof(struct parport_private));
+ ret = alloc_private(dev, sizeof(*devpriv));
if (ret < 0)
return ret;
+ devpriv = dev->private;
s = dev->subdevices + 0;
s->type = COMEDI_SUBD_DIO;
devpriv->c_data = 0;
outb(devpriv->c_data, dev->iobase + PARPORT_C);
- printk(KERN_INFO "\n");
- return 1;
+ dev_info(dev->class_dev, "%s: iobase=0x%04lx, irq %sabled",
+ dev->board_name, dev->iobase, dev->irq ? "en" : "dis");
+
+ return 0;
}
static void parport_detach(struct comedi_device *dev)
#include "comedi_fc.h"
#include <linux/timer.h>
-/* Board descriptions */
-struct waveform_board {
- const char *name;
- int ai_chans;
- int ai_bits;
- int have_dio;
-};
-
#define N_CHANS 8
/* Data unique to this driver */
unsigned timer_running:1;
unsigned int ao_loopbacks[N_CHANS];
};
-#define devpriv ((struct waveform_private *)dev->private)
/* 1000 nanosec in a microsec */
static const int nano_per_micro = 1000;
static short fake_sawtooth(struct comedi_device *dev, unsigned int range_index,
unsigned long current_time)
{
+ struct waveform_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
unsigned int offset = s->maxdata / 2;
u64 value;
unsigned int range_index,
unsigned long current_time)
{
+ struct waveform_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
unsigned int offset = s->maxdata / 2;
u64 value;
static void waveform_ai_interrupt(unsigned long arg)
{
struct comedi_device *dev = (struct comedi_device *)arg;
+ struct waveform_private *devpriv = dev->private;
struct comedi_async *async = dev->read_subdev->async;
struct comedi_cmd *cmd = &async->cmd;
unsigned int i, j;
static int waveform_ai_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{
+ struct waveform_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
if (cmd->flags & TRIG_RT) {
static int waveform_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
+ struct waveform_private *devpriv = dev->private;
+
devpriv->timer_running = 0;
del_timer(&devpriv->timer);
return 0;
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct waveform_private *devpriv = dev->private;
int i, chan = CR_CHAN(insn->chanspec);
for (i = 0; i < insn->n; i++)
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct waveform_private *devpriv = dev->private;
int i, chan = CR_CHAN(insn->chanspec);
for (i = 0; i < insn->n; i++)
static int waveform_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
- const struct waveform_board *board = comedi_board(dev);
+ struct waveform_private *devpriv;
struct comedi_subdevice *s;
int amplitude = it->options[0];
int period = it->options[1];
int i;
int ret;
- dev->board_name = board->name;
+ dev->board_name = dev->driver->driver_name;
- if (alloc_private(dev, sizeof(struct waveform_private)) < 0)
- return -ENOMEM;
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret < 0)
+ return ret;
+ devpriv = dev->private;
/* set default amplitude and period */
if (amplitude <= 0)
/* analog input subdevice */
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
- s->n_chan = board->ai_chans;
- s->maxdata = (1 << board->ai_bits) - 1;
+ s->n_chan = N_CHANS;
+ s->maxdata = 0xffff;
s->range_table = &waveform_ai_ranges;
s->len_chanlist = s->n_chan * 2;
s->insn_read = waveform_ai_insn_read;
/* analog output subdevice (loopback) */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
- s->n_chan = board->ai_chans;
- s->maxdata = (1 << board->ai_bits) - 1;
+ s->n_chan = N_CHANS;
+ s->maxdata = 0xffff;
s->range_table = &waveform_ai_ranges;
s->len_chanlist = s->n_chan * 2;
s->insn_write = waveform_ao_insn_write;
devpriv->timer.function = waveform_ai_interrupt;
devpriv->timer.data = (unsigned long)dev;
- printk(KERN_INFO "comedi%d: comedi_test: "
- "%i microvolt, %li microsecond waveform attached\n", dev->minor,
- devpriv->uvolt_amplitude, devpriv->usec_period);
- return 1;
+ dev_info(dev->class_dev,
+ "%s: %i microvolt, %li microsecond waveform attached\n",
+ dev->board_name,
+ devpriv->uvolt_amplitude, devpriv->usec_period);
+
+ return 0;
}
static void waveform_detach(struct comedi_device *dev)
{
- if (dev->private)
+ struct waveform_private *devpriv = dev->private;
+
+ if (devpriv)
waveform_ai_cancel(dev, dev->read_subdev);
}
-static const struct waveform_board waveform_boards[] = {
- {
- .name = "comedi_test",
- .ai_chans = N_CHANS,
- .ai_bits = 16,
- .have_dio = 0,
- },
-};
-
static struct comedi_driver waveform_driver = {
.driver_name = "comedi_test",
.module = THIS_MODULE,
.attach = waveform_attach,
.detach = waveform_detach,
- .board_name = &waveform_boards[0].name,
- .offset = sizeof(struct waveform_board),
- .num_names = ARRAY_SIZE(waveform_boards),
};
module_comedi_driver(waveform_driver);
Updated: Wed, 27 Jun 2007 13:00:06 +0100
Status: works
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
+Configuration Options: not applicable, uses comedi PCI auto config
*/
#include "../comedidev.h"
-enum contec_model {
- PIO1616L = 0,
-};
-
-struct contec_board {
- const char *name;
- int model;
- int in_ports;
- int out_ports;
- int in_offs;
- int out_offs;
- int out_boffs;
-};
-static const struct contec_board contec_boards[] = {
- {"PIO1616L", PIO1616L, 16, 16, 0, 2, 10},
-};
-
#define PCI_DEVICE_ID_PIO1616L 0x8172
-#define thisboard ((const struct contec_board *)dev->board_ptr)
+/*
+ * Register map
+ */
+#define PIO1616L_DI_REG 0x00
+#define PIO1616L_DO_REG 0x02
static int contec_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ unsigned int mask = data[0];
+ unsigned int bits = data[1];
- dev_dbg(dev->class_dev, "contec_do_insn_bits called\n");
- dev_dbg(dev->class_dev, "data: %d %d\n", data[0], data[1]);
+ if (mask) {
+ s->state &= ~mask;
+ s->state |= (bits & mask);
- if (data[0]) {
- s->state &= ~data[0];
- s->state |= data[0] & data[1];
- dev_dbg(dev->class_dev, "out: %d on %lx\n", s->state,
- dev->iobase + thisboard->out_offs);
- outw(s->state, dev->iobase + thisboard->out_offs);
+ outw(s->state, dev->iobase + PIO1616L_DO_REG);
}
+
+ data[1] = s->state;
+
return insn->n;
}
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
-
- dev_dbg(dev->class_dev, "contec_di_insn_bits called\n");
- dev_dbg(dev->class_dev, "data: %d %d\n", data[0], data[1]);
-
- data[1] = inw(dev->iobase + thisboard->in_offs);
+ data[1] = inw(dev->iobase + PIO1616L_DI_REG);
return insn->n;
}
-static struct pci_dev *contec_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int contec_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
-
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_CONTEC ||
- pcidev->device != PCI_DEVICE_ID_PIO1616L)
- continue;
-
- dev->board_ptr = contec_boards + 0;
- return pcidev;
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev;
struct comedi_subdevice *s;
int ret;
- printk("comedi%d: contec: ", dev->minor);
+ comedi_set_hw_dev(dev, &pcidev->dev);
- dev->board_name = thisboard->name;
+ dev->board_name = dev->driver->driver_name;
- ret = comedi_alloc_subdevices(dev, 2);
+ ret = comedi_pci_enable(pcidev, dev->board_name);
if (ret)
return ret;
-
- pcidev = contec_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
- comedi_set_hw_dev(dev, &pcidev->dev);
-
- if (comedi_pci_enable(pcidev, "contec_pci_dio")) {
- printk("error enabling PCI device and request regions!\n");
- return -EIO;
- }
dev->iobase = pci_resource_start(pcidev, 0);
- printk(" base addr %lx ", dev->iobase);
- s = dev->subdevices + 0;
+ ret = comedi_alloc_subdevices(dev, 2);
+ if (ret)
+ return ret;
- s->type = COMEDI_SUBD_DI;
- s->subdev_flags = SDF_READABLE;
- s->n_chan = 16;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = contec_di_insn_bits;
+ s = dev->subdevices + 0;
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = contec_di_insn_bits;
s = dev->subdevices + 1;
- s->type = COMEDI_SUBD_DO;
- s->subdev_flags = SDF_WRITABLE;
- s->n_chan = 16;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = contec_do_insn_bits;
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_WRITABLE;
+ s->n_chan = 16;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = contec_do_insn_bits;
- printk("attached\n");
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
- return 1;
+ return 0;
}
static void contec_detach(struct comedi_device *dev)
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver contec_pci_dio_driver = {
.driver_name = "contec_pci_dio",
.module = THIS_MODULE,
- .attach = contec_attach,
+ .attach_pci = contec_attach_pci,
.detach = contec_detach,
};
}
static DEFINE_PCI_DEVICE_TABLE(contec_pci_dio_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L),
- .driver_data = PIO1616L },
+ { PCI_DEVICE(PCI_VENDOR_ID_CONTEC, PCI_DEVICE_ID_PIO1616L) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, contec_pci_dio_pci_table);
#include <linux/mutex.h>
#define PCI_VENDOR_ID_DYNALOG 0x10b5
-#define DRV_NAME "dyna_pci10xx"
#define READ_TIMEOUT 50
static const char range_codes_pci1050_ai[] = { 0x00, 0x10, 0x30 };
-static const struct comedi_lrange range_pci1050_ao = { 1, {
- UNI_RANGE(10)
- }
-};
-
-static const char range_codes_pci1050_ao[] = { 0x00 };
-
-struct boardtype {
- const char *name;
- int device_id;
- int ai_chans;
- int ai_bits;
- int ao_chans;
- int ao_bits;
- int di_chans;
- int di_bits;
- int do_chans;
- int do_bits;
- const struct comedi_lrange *range_ai;
- const char *range_codes_ai;
- const struct comedi_lrange *range_ao;
- const char *range_codes_ao;
-};
-
-static const struct boardtype boardtypes[] = {
- {
- .name = "dyna_pci1050",
- .device_id = 0x1050,
- .ai_chans = 16,
- .ai_bits = 12,
- .ao_chans = 16,
- .ao_bits = 12,
- .di_chans = 16,
- .di_bits = 16,
- .do_chans = 16,
- .do_bits = 16,
- .range_ai = &range_pci1050_ai,
- .range_codes_ai = range_codes_pci1050_ai,
- .range_ao = &range_pci1050_ao,
- .range_codes_ao = range_codes_pci1050_ao,
- },
- /* dummy entry corresponding to driver name */
- {.name = DRV_NAME},
-};
-
struct dyna_pci10xx_private {
struct mutex mutex;
unsigned long BADR3;
};
-#define thisboard ((const struct boardtype *)dev->board_ptr)
-#define devpriv ((struct dyna_pci10xx_private *)dev->private)
-
/******************************************************************************/
/************************** READ WRITE FUNCTIONS ******************************/
/******************************************************************************/
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct dyna_pci10xx_private *devpriv = dev->private;
int n, counter;
u16 d = 0;
unsigned int chan, range;
/* get the channel number and range */
chan = CR_CHAN(insn->chanspec);
- range = thisboard->range_codes_ai[CR_RANGE((insn->chanspec))];
+ range = range_codes_pci1050_ai[CR_RANGE((insn->chanspec))];
mutex_lock(&devpriv->mutex);
/* convert n samples */
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct dyna_pci10xx_private *devpriv = dev->private;
int n;
unsigned int chan, range;
chan = CR_CHAN(insn->chanspec);
- range = thisboard->range_codes_ai[CR_RANGE((insn->chanspec))];
+ range = range_codes_pci1050_ai[CR_RANGE((insn->chanspec))];
mutex_lock(&devpriv->mutex);
for (n = 0; n < insn->n; n++) {
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct dyna_pci10xx_private *devpriv = dev->private;
u16 d = 0;
mutex_lock(&devpriv->mutex);
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
+ struct dyna_pci10xx_private *devpriv = dev->private;
+
/* The insn data is a mask in data[0] and the new data
* in data[1], each channel cooresponding to a bit.
* s->state contains the previous write data
return insn->n;
}
-static struct pci_dev *dyna_pci10xx_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
-{
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
- int i;
-
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (bus != pcidev->bus->number ||
- slot != PCI_SLOT(pcidev->devfn))
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_DYNALOG)
- continue;
-
- for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
- if (pcidev->device != boardtypes[i].device_id)
- continue;
-
- dev->board_ptr = &boardtypes[i];
- return pcidev;
- }
- }
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
- return NULL;
-}
-
-static int dyna_pci10xx_attach(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static int dyna_pci10xx_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
- struct pci_dev *pcidev;
+ struct dyna_pci10xx_private *devpriv;
struct comedi_subdevice *s;
int ret;
- if (alloc_private(dev, sizeof(struct dyna_pci10xx_private)) < 0) {
- printk(KERN_ERR "comedi: dyna_pci10xx: "
- "failed to allocate memory!\n");
- return -ENOMEM;
- }
-
- pcidev = dyna_pci10xx_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
comedi_set_hw_dev(dev, &pcidev->dev);
- dev->board_name = thisboard->name;
- dev->irq = 0;
-
- if (comedi_pci_enable(pcidev, DRV_NAME)) {
- printk(KERN_ERR "comedi: dyna_pci10xx: "
- "failed to enable PCI device and request regions!");
- return -EIO;
- }
-
- mutex_init(&devpriv->mutex);
+ dev->board_name = dev->driver->driver_name;
- printk(KERN_INFO "comedi: dyna_pci10xx: device found!\n");
+ ret = alloc_private(dev, sizeof(*devpriv));
+ if (ret)
+ return ret;
+ devpriv = dev->private;
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
dev->iobase = pci_resource_start(pcidev, 2);
devpriv->BADR3 = pci_resource_start(pcidev, 3);
+ mutex_init(&devpriv->mutex);
+
ret = comedi_alloc_subdevices(dev, 4);
if (ret)
return ret;
s = dev->subdevices + 0;
s->type = COMEDI_SUBD_AI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
- s->n_chan = thisboard->ai_chans;
+ s->n_chan = 16;
s->maxdata = 0x0FFF;
- s->range_table = thisboard->range_ai;
+ s->range_table = &range_pci1050_ai;
s->len_chanlist = 16;
s->insn_read = dyna_pci10xx_insn_read_ai;
s = dev->subdevices + 1;
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE;
- s->n_chan = thisboard->ao_chans;
+ s->n_chan = 16;
s->maxdata = 0x0FFF;
- s->range_table = thisboard->range_ao;
+ s->range_table = &range_unipolar10;
s->len_chanlist = 16;
s->insn_write = dyna_pci10xx_insn_write_ao;
s = dev->subdevices + 2;
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_GROUND;
- s->n_chan = thisboard->di_chans;
+ s->n_chan = 16;
s->maxdata = 1;
s->range_table = &range_digital;
- s->len_chanlist = thisboard->di_chans;
+ s->len_chanlist = 16;
s->insn_bits = dyna_pci10xx_di_insn_bits;
/* digital output */
s = dev->subdevices + 3;
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
- s->n_chan = thisboard->do_chans;
+ s->n_chan = 16;
s->maxdata = 1;
s->range_table = &range_digital;
- s->len_chanlist = thisboard->do_chans;
+ s->len_chanlist = 16;
s->state = 0;
s->insn_bits = dyna_pci10xx_do_insn_bits;
- printk(KERN_INFO "comedi: dyna_pci10xx: %s - device setup completed!\n",
- thisboard->name);
+ dev_info(dev->class_dev, "%s attached\n", dev->board_name);
- return 1;
+ return 0;
}
static void dyna_pci10xx_detach(struct comedi_device *dev)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
+ struct dyna_pci10xx_private *devpriv = dev->private;
if (devpriv)
mutex_destroy(&devpriv->mutex);
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver dyna_pci10xx_driver = {
.driver_name = "dyna_pci10xx",
.module = THIS_MODULE,
- .attach = dyna_pci10xx_attach,
+ .attach_pci = dyna_pci10xx_attach_pci,
.detach = dyna_pci10xx_detach,
- .board_name = &boardtypes[0].name,
- .offset = sizeof(struct boardtype),
- .num_names = ARRAY_SIZE(boardtypes),
};
static int __devinit dyna_pci10xx_pci_probe(struct pci_dev *dev,
Updated: Mon, 14 Apr 2008 15:42:42 +0100
Status: tested
-Configuration Options:
- [0] - PCI bus of device (optional)
- [1] - PCI slot of device (optional)
- If bus/slot is not specified, the first supported
- PCI device found will be used.
+Configuration Options: not applicable, uses PCI auto config
This driver is a simple driver to read the counter values from
Kolter Electronic PCI Counter Card.
return 1;
}
-static struct pci_dev *cnt_find_pci_dev(struct comedi_device *dev,
- struct comedi_devconfig *it)
+static const void *cnt_find_boardinfo(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
const struct cnt_board_struct *board;
- struct pci_dev *pcidev = NULL;
- int bus = it->options[0];
- int slot = it->options[1];
int i;
- /* Probe the device to determine what device in the series it is. */
- for_each_pci_dev(pcidev) {
- if (bus || slot) {
- if (pcidev->bus->number != bus ||
- PCI_SLOT(pcidev->devfn) != slot)
- continue;
- }
- if (pcidev->vendor != PCI_VENDOR_ID_KOLTER)
- continue;
-
- for (i = 0; i < ARRAY_SIZE(cnt_boards); i++) {
- board = &cnt_boards[i];
- if (board->device_id != pcidev->device)
- continue;
-
- dev->board_ptr = board;
- return pcidev;
- }
+ for (i = 0; i < ARRAY_SIZE(cnt_boards); i++) {
+ board = &cnt_boards[i];
+ if (board->device_id == pcidev->device)
+ return board;
}
- dev_err(dev->class_dev,
- "No supported board found! (req. bus %d, slot %d)\n",
- bus, slot);
return NULL;
}
-static int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+static int cnt_attach_pci(struct comedi_device *dev,
+ struct pci_dev *pcidev)
{
const struct cnt_board_struct *board;
- struct pci_dev *pcidev;
struct comedi_subdevice *subdevice;
- unsigned long io_base;
- int error;
+ int ret;
- pcidev = cnt_find_pci_dev(dev, it);
- if (!pcidev)
- return -EIO;
comedi_set_hw_dev(dev, &pcidev->dev);
- board = comedi_board(dev);
+ board = cnt_find_boardinfo(dev, pcidev);
+ if (!board)
+ return -ENODEV;
+ dev->board_ptr = board;
dev->board_name = board->name;
- /* enable PCI device and request regions */
- error = comedi_pci_enable(pcidev, CNT_DRIVER_NAME);
- if (error < 0) {
- printk(KERN_WARNING "comedi%d: "
- "failed to enable PCI device and request regions!\n",
- dev->minor);
- return error;
- }
-
- /* read register base address [PCI_BASE_ADDRESS #0] */
- io_base = pci_resource_start(pcidev, 0);
- dev->iobase = io_base;
+ ret = comedi_pci_enable(pcidev, dev->board_name);
+ if (ret)
+ return ret;
+ dev->iobase = pci_resource_start(pcidev, 0);
- error = comedi_alloc_subdevices(dev, 1);
- if (error)
- return error;
+ ret = comedi_alloc_subdevices(dev, 1);
+ if (ret)
+ return ret;
subdevice = dev->subdevices + 0;
dev->read_subdev = subdevice;
outb(0, dev->iobase + 0x20);
outb(0, dev->iobase + 0x40);
- printk(KERN_INFO "comedi%d: " CNT_DRIVER_NAME " attached.\n",
- dev->minor);
+ dev_info(dev->class_dev, "%s: %s attached\n",
+ dev->driver->driver_name, dev->board_name);
+
return 0;
}
if (pcidev) {
if (dev->iobase)
comedi_pci_disable(pcidev);
- pci_dev_put(pcidev);
}
}
static struct comedi_driver ke_counter_driver = {
.driver_name = "ke_counter",
.module = THIS_MODULE,
- .attach = cnt_attach,
+ .attach_pci = cnt_attach_pci,
.detach = cnt_detach,
};
struct comedi_subdevice *s;
int ret;
- printk(KERN_INFO "comedi%d: dnp: ", dev->minor);
-
dev->board_name = board->name;
ret = comedi_alloc_subdevices(dev, 1);
s->insn_bits = dnp_dio_insn_bits;
s->insn_config = dnp_dio_insn_config;
- printk("attached\n");
-
/* We use the I/O ports 0x22,0x23 and 0xa3-0xa9, which are always
* allocated for the primary 8259, so we don't need to allocate them
* ourselves. */
outb(PCMR, CSCIR);
outb((inb(CSCDR) & 0xAA), CSCDR);
+ dev_info(dev->class_dev, "%s: attached\n", dev->board_name);
return 1;
}
int comedi_check_chanlist(struct comedi_subdevice *s, int n,
unsigned int *chanlist)
{
+ struct comedi_device *dev = s->device;
int i;
int chan;
if (CR_CHAN(chanlist[i]) >= s->n_chan ||
CR_RANGE(chanlist[i]) >= s->range_table->length
|| aref_invalid(s, chanlist[i])) {
- printk(KERN_ERR "bad chanlist[%d]=0x%08x "
- "in_chan=%d range length=%d\n", i,
- chanlist[i], s->n_chan,
- s->range_table->length);
+ dev_warn(dev->class_dev,
+ "bad chanlist[%d]=0x%08x in_chan=%d range length=%d\n",
+ i, chanlist[i], s->n_chan,
+ s->range_table->length);
return -EINVAL;
}
} else if (s->range_table_list) {
CR_RANGE(chanlist[i]) >=
s->range_table_list[chan]->length
|| aref_invalid(s, chanlist[i])) {
- printk(KERN_ERR "bad chanlist[%d]=0x%08x\n",
- i, chanlist[i]);
+ dev_warn(dev->class_dev,
+ "bad chanlist[%d]=0x%08x\n",
+ i, chanlist[i]);
return -EINVAL;
}
}
} else {
- printk(KERN_ERR "comedi: (bug) no range type list!\n");
+ dev_err(dev->class_dev, "(bug) no range type list!\n");
return -EINVAL;
}
return 0;
/* register crystalhd class */
crystalhd_class = class_create(THIS_MODULE, "crystalhd");
if (IS_ERR(crystalhd_class)) {
+ rc = PTR_ERR(crystalhd_class);
BCMLOG_ERR("failed to create class\n");
- goto fail;
+ goto class_create_fail;
}
dev = device_create(crystalhd_class, NULL, MKDEV(adp->chd_dec_major, 0),
NULL, "crystalhd");
if (IS_ERR(dev)) {
+ rc = PTR_ERR(crystalhd_class);
BCMLOG_ERR("failed to create device\n");
goto device_create_fail;
}
device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
device_create_fail:
class_destroy(crystalhd_class);
+class_create_fail:
+ unregister_chrdev(adp->chd_dec_major, CRYSTALHD_API_NAME);
fail:
return rc;
}
unifi_event.o \
unifi_pdu_processing.o \
unifi_sme.o \
- csr_formatted_io.o \
csr_wifi_hip_card_sdio.o \
csr_wifi_hip_card_sdio_intr.o \
csr_wifi_hip_card_sdio_mem.o \
* 0 on success or else a Linux error code.
* ---------------------------------------------------------------------------
*/
-int
-uf_start_thread(unifi_priv_t *priv, struct uf_thread *thread, int (*func)(void *))
+int uf_start_thread(unifi_priv_t *priv,
+ struct uf_thread *thread, int (*func)(void *))
{
- if (thread->thread_task != NULL) {
- unifi_error(priv, "%s thread already started\n", thread->name);
- return 0;
- }
-
- /* Start the kernel thread that handles all h/w accesses. */
- thread->thread_task = kthread_run(func, priv, "%s", thread->name);
- if (IS_ERR(thread->thread_task)) {
- return PTR_ERR(thread->thread_task);
- }
-
- /* Module parameter overides the thread priority */
- if (bh_priority != -1) {
- if (bh_priority >= 0 && bh_priority <= MAX_RT_PRIO) {
- struct sched_param param;
- priv->bh_thread.prio = bh_priority;
- unifi_trace(priv, UDBG1, "%s thread (RT) priority = %d\n",
- thread->name, bh_priority);
- param.sched_priority = bh_priority;
- sched_setscheduler(thread->thread_task, SCHED_FIFO, ¶m);
- } else if (bh_priority > MAX_RT_PRIO && bh_priority <= MAX_PRIO) {
- priv->bh_thread.prio = bh_priority;
- unifi_trace(priv, UDBG1, "%s thread priority = %d\n",
- thread->name, PRIO_TO_NICE(bh_priority));
- set_user_nice(thread->thread_task, PRIO_TO_NICE(bh_priority));
- } else {
- priv->bh_thread.prio = DEFAULT_PRIO;
- unifi_warning(priv, "%s thread unsupported (%d) priority\n",
- thread->name, bh_priority);
- }
- } else {
- priv->bh_thread.prio = DEFAULT_PRIO;
- }
- unifi_trace(priv, UDBG2, "Started %s thread\n", thread->name);
-
- return 0;
+ if (thread->thread_task != NULL) {
+ unifi_error(priv, "%s thread already started\n", thread->name);
+ return 0;
+ }
+
+ /* Start the kernel thread that handles all h/w accesses. */
+ thread->thread_task = kthread_run(func, priv, "%s", thread->name);
+ if (IS_ERR(thread->thread_task))
+ return PTR_ERR(thread->thread_task);
+
+ /* Module parameter overides the thread priority */
+ if (bh_priority != -1) {
+ if (bh_priority >= 0 && bh_priority <= MAX_RT_PRIO) {
+ struct sched_param param;
+ priv->bh_thread.prio = bh_priority;
+ unifi_trace(priv, UDBG1,
+ "%s thread (RT) priority = %d\n",
+ thread->name, bh_priority);
+ param.sched_priority = bh_priority;
+ sched_setscheduler(thread->thread_task,
+ SCHED_FIFO, ¶m);
+ } else if (bh_priority > MAX_RT_PRIO &&
+ bh_priority <= MAX_PRIO) {
+ priv->bh_thread.prio = bh_priority;
+ unifi_trace(priv, UDBG1, "%s thread priority = %d\n",
+ thread->name,
+ PRIO_TO_NICE(bh_priority));
+ set_user_nice(thread->thread_task,
+ PRIO_TO_NICE(bh_priority));
+ } else {
+ priv->bh_thread.prio = DEFAULT_PRIO;
+ unifi_warning(priv,
+ "%s thread unsupported (%d) priority\n",
+ thread->name, bh_priority);
+ }
+ } else
+ priv->bh_thread.prio = DEFAULT_PRIO;
+ unifi_trace(priv, UDBG2, "Started %s thread\n", thread->name);
+
+ return 0;
} /* uf_start_thread() */
*
* ---------------------------------------------------------------------------
*/
- void
-uf_stop_thread(unifi_priv_t *priv, struct uf_thread *thread)
+void uf_stop_thread(unifi_priv_t *priv, struct uf_thread *thread)
{
- if (!thread->thread_task) {
- unifi_notice(priv, "%s thread is already stopped\n", thread->name);
- return;
- }
+ if (!thread->thread_task) {
+ unifi_notice(priv, "%s thread is already stopped\n",
+ thread->name);
+ return;
+ }
- unifi_trace(priv, UDBG2, "Stopping %s thread\n", thread->name);
+ unifi_trace(priv, UDBG2, "Stopping %s thread\n", thread->name);
- kthread_stop(thread->thread_task);
- thread->thread_task = NULL;
+ kthread_stop(thread->thread_task);
+ thread->thread_task = NULL;
} /* uf_stop_thread() */
*
* ---------------------------------------------------------------------------
*/
- void
+void
uf_wait_for_thread_to_stop(unifi_priv_t *priv, struct uf_thread *thread)
{
- /*
- * kthread_stop() cannot handle the thread exiting while
- * kthread_should_stop() is false, so sleep until kthread_stop()
- * wakes us up.
- */
- unifi_trace(priv, UDBG2, "%s waiting for the stop signal.\n", thread->name);
- set_current_state(TASK_INTERRUPTIBLE);
- if (!kthread_should_stop()) {
- unifi_trace(priv, UDBG2, "%s schedule....\n", thread->name);
- schedule();
- }
-
- thread->thread_task = NULL;
- unifi_trace(priv, UDBG2, "%s exiting....\n", thread->name);
+ /*
+ * kthread_stop() cannot handle the thread exiting while
+ * kthread_should_stop() is false, so sleep until kthread_stop()
+ * wakes us up
+ */
+ unifi_trace(priv, UDBG2, "%s waiting for the stop signal.\n",
+ thread->name);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (!kthread_should_stop()) {
+ unifi_trace(priv, UDBG2, "%s schedule....\n", thread->name);
+ schedule();
+ }
+
+ thread->thread_task = NULL;
+ unifi_trace(priv, UDBG2, "%s exiting....\n", thread->name);
} /* uf_wait_for_thread_to_stop() */
* None.
* ---------------------------------------------------------------------------
*/
- static void
+static void
handle_bh_error(unifi_priv_t *priv)
{
- u8 conf_param = CONFIG_IND_ERROR;
- u8 interfaceTag = 0; /* used as a loop counter */
+ netInterface_priv_t *interfacePriv;
+ u8 conf_param = CONFIG_IND_ERROR;
+ u8 interfaceTag;
- /* Block unifi_run_bh() until the error has been handled. */
- priv->bh_thread.block_thread = 1;
+ /* Block unifi_run_bh() until the error has been handled. */
+ priv->bh_thread.block_thread = 1;
- /* Consider UniFi to be uninitialised */
- priv->init_progress = UNIFI_INIT_NONE;
+ /* Consider UniFi to be uninitialised */
+ priv->init_progress = UNIFI_INIT_NONE;
- /* Stop the network traffic */
- for( interfaceTag =0; interfaceTag <CSR_WIFI_NUM_INTERFACES;interfaceTag ++) {
- netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
- if (interfacePriv->netdev_registered == 1) {
- netif_carrier_off(priv->netdev[interfaceTag]);
- }
- }
+ /* Stop the network traffic */
+ for (interfaceTag = 0;
+ interfaceTag < CSR_WIFI_NUM_INTERFACES; interfaceTag++) {
+ interfacePriv = priv->interfacePriv[interfaceTag];
+ if (interfacePriv->netdev_registered)
+ netif_carrier_off(priv->netdev[interfaceTag]);
+ }
#ifdef CSR_NATIVE_LINUX
- /* Force any client waiting on an mlme_wait_for_reply() to abort. */
- uf_abort_mlme(priv);
+ /* Force any client waiting on an mlme_wait_for_reply() to abort. */
+ uf_abort_mlme(priv);
- /* Cancel any pending workqueue tasks */
- flush_workqueue(priv->unifi_workqueue);
+ /* Cancel any pending workqueue tasks */
+ flush_workqueue(priv->unifi_workqueue);
#endif /* CSR_NATIVE_LINUX */
- unifi_error(priv, "handle_bh_error: fatal error is reported to the SME.\n");
- /* Notify the clients (SME or unifi_manager) for the error. */
- ul_log_config_ind(priv, &conf_param, sizeof(u8));
+ unifi_error(priv,
+ "handle_bh_error: fatal error is reported to the SME.\n");
+ /* Notify the clients (SME or unifi_manager) for the error. */
+ ul_log_config_ind(priv, &conf_param, sizeof(u8));
} /* handle_bh_error() */
+++ /dev/null
-/*****************************************************************************
-
- (c) Cambridge Silicon Radio Limited 2010
- All rights reserved and confidential information of CSR
-
- Refer to LICENSE.txt included with this source for details
- on the license terms.
-
-*****************************************************************************/
-#include <linux/kernel.h>
-#include "csr_formatted_io.h"
-
-s32 CsrSnprintf(char *dest, size_t n, const char *fmt, ...)
-{
- s32 r;
- va_list args;
- va_start(args, fmt);
- r = vsnprintf(dest, n, fmt, args);
- va_end(args);
-
- if (dest && (n > 0))
- {
- dest[n - 1] = '\0';
- }
-
- return r;
-}
+++ /dev/null
-#ifndef CSR_FORMATTED_IO_H__
-#define CSR_FORMATTED_IO_H__
-/*****************************************************************************
-
- (c) Cambridge Silicon Radio Limited 2010
- All rights reserved and confidential information of CSR
-
- Refer to LICENSE.txt included with this source for details
- on the license terms.
-
-*****************************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <linux/types.h>
-
-s32 CsrSnprintf(char *dest, size_t n, const char *fmt, ...);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
*****************************************************************************/
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/module.h>
#include "csr_panic.h"
CsrTime CsrTimeGet(CsrTime *high)
{
- struct timespec ts;
- u64 time;
- CsrTime low;
+ struct timespec ts;
+ u64 time;
+ CsrTime low;
- ts = current_kernel_time();
- time = (u64) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
+ ts = current_kernel_time();
+ time = (u64) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
- if (high != NULL)
- {
- *high = (CsrTime) ((time >> 32) & 0xFFFFFFFF);
- }
+ if (high != NULL)
+ *high = (CsrTime) ((time >> 32) & 0xFFFFFFFF);
- low = (CsrTime) (time & 0xFFFFFFFF);
+ low = (CsrTime) (time & 0xFFFFFFFF);
- return low;
+ return low;
}
EXPORT_SYMBOL_GPL(CsrTimeGet);
/* Reset any state carried forward from a previous life */
card->fh_command_queue.q_rd_ptr = 0;
card->fh_command_queue.q_wr_ptr = 0;
- (void)CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH,
+ (void)scnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH,
"fh_cmd_q");
for (i = 0; i < UNIFI_NO_OF_TX_QS; i++)
{
card->fh_traffic_queue[i].q_rd_ptr = 0;
card->fh_traffic_queue[i].q_wr_ptr = 0;
- (void)CsrSnprintf(card->fh_traffic_queue[i].name,
+ (void)scnprintf(card->fh_traffic_queue[i].name,
UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i);
}
#ifndef CSR_WIFI_HIP_TA_DISABLE
/* Reset any state carried forward from a previous life */
card->fh_command_queue.q_rd_ptr = 0;
card->fh_command_queue.q_wr_ptr = 0;
- (void)CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH,
+ (void)scnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH,
"fh_cmd_q");
for (i = 0; i < UNIFI_NO_OF_TX_QS; i++)
{
card->fh_traffic_queue[i].q_rd_ptr = 0;
card->fh_traffic_queue[i].q_wr_ptr = 0;
- (void)CsrSnprintf(card->fh_traffic_queue[i].name,
+ (void)scnprintf(card->fh_traffic_queue[i].name,
UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i);
}
#ifndef CSR_WIFI_HIP_TA_DISABLE
{
const u8 *sig = sigptr;
- unifi_error(card->ospriv, "Signal(%d): %02x %02x %02x %02x %02x %02x %02x %02x"
- " %02x %02x %02x %02x %02x %02x %02x %02x\n",
- siglen,
- sig[0], sig[1], sig[2], sig[3],
- sig[4], sig[5], sig[6], sig[7],
- sig[8], sig[9], sig[10], sig[11],
- sig[12], sig[13], sig[14], sig[15]);
+ unifi_error(card->ospriv, "Signal(%d): %*ph\n", siglen,
+ 16, sig);
unifi_error(card->ospriv, "Bulkdata pointer %p(%d), %p(%d)\n",
bulkdata != NULL?bulkdata->d[0].os_data_ptr : NULL,
bulkdata != NULL?bulkdata->d[0].data_length : 0,
}
i = n = 0;
- written = CsrSnprintf(p, remaining, "Chip ID %u\n",
+ written = scnprintf(p, remaining, "Chip ID %u\n",
(u16)card->chip_id);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "Chip Version %04X\n",
+ written = scnprintf(p, remaining, "Chip Version %04X\n",
card->chip_version);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "HIP v%u.%u\n",
+ written = scnprintf(p, remaining, "HIP v%u.%u\n",
(card->config_data.version >> 8) & 0xFF,
card->config_data.version & 0xFF);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "Build %lu: %s\n",
+ written = scnprintf(p, remaining, "Build %u: %s\n",
card->build_id, card->build_id_string);
UNIFI_SNPRINTF_RET(p, remaining, written);
cfg = &card->config_data;
- written = CsrSnprintf(p, remaining, "sdio ctrl offset %u\n",
+ written = scnprintf(p, remaining, "sdio ctrl offset %u\n",
cfg->sdio_ctrl_offset);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "fromhost sigbuf handle %u\n",
+ written = scnprintf(p, remaining, "fromhost sigbuf handle %u\n",
cfg->fromhost_sigbuf_handle);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "tohost_sigbuf_handle %u\n",
+ written = scnprintf(p, remaining, "tohost_sigbuf_handle %u\n",
cfg->tohost_sigbuf_handle);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "num_fromhost_sig_frags %u\n",
+ written = scnprintf(p, remaining, "num_fromhost_sig_frags %u\n",
cfg->num_fromhost_sig_frags);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "num_tohost_sig_frags %u\n",
+ written = scnprintf(p, remaining, "num_tohost_sig_frags %u\n",
cfg->num_tohost_sig_frags);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "num_fromhost_data_slots %u\n",
+ written = scnprintf(p, remaining, "num_fromhost_data_slots %u\n",
cfg->num_fromhost_data_slots);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "num_tohost_data_slots %u\n",
+ written = scnprintf(p, remaining, "num_tohost_data_slots %u\n",
cfg->num_tohost_data_slots);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "data_slot_size %u\n",
+ written = scnprintf(p, remaining, "data_slot_size %u\n",
cfg->data_slot_size);
UNIFI_SNPRINTF_RET(p, remaining, written);
/* Added by protocol version 0x0001 */
- written = CsrSnprintf(p, remaining, "overlay_size %u\n",
+ written = scnprintf(p, remaining, "overlay_size %u\n",
(u16)cfg->overlay_size);
UNIFI_SNPRINTF_RET(p, remaining, written);
/* Added by protocol version 0x0300 */
- written = CsrSnprintf(p, remaining, "data_slot_round %u\n",
+ written = scnprintf(p, remaining, "data_slot_round %u\n",
cfg->data_slot_round);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "sig_frag_size %u\n",
+ written = scnprintf(p, remaining, "sig_frag_size %u\n",
cfg->sig_frag_size);
UNIFI_SNPRINTF_RET(p, remaining, written);
/* Added by protocol version 0x0300 */
- written = CsrSnprintf(p, remaining, "tohost_sig_pad %u\n",
+ written = scnprintf(p, remaining, "tohost_sig_pad %u\n",
cfg->tohost_signal_padding);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "\nInternal state:\n");
+ written = scnprintf(p, remaining, "\nInternal state:\n");
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "Last PHY PANIC: %04x:%04x\n",
+ written = scnprintf(p, remaining, "Last PHY PANIC: %04x:%04x\n",
card->last_phy_panic_code, card->last_phy_panic_arg);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "Last MAC PANIC: %04x:%04x\n",
+ written = scnprintf(p, remaining, "Last MAC PANIC: %04x:%04x\n",
card->last_mac_panic_code, card->last_mac_panic_arg);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "fhsr: %u\n",
+ written = scnprintf(p, remaining, "fhsr: %u\n",
(u16)card->from_host_signals_r);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "fhsw: %u\n",
+ written = scnprintf(p, remaining, "fhsw: %u\n",
(u16)card->from_host_signals_w);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "thsr: %u\n",
+ written = scnprintf(p, remaining, "thsr: %u\n",
(u16)card->to_host_signals_r);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "thsw: %u\n",
+ written = scnprintf(p, remaining, "thsw: %u\n",
(u16)card->to_host_signals_w);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining,
- "fh buffer contains: %u signals, %u bytes\n",
+ written = scnprintf(p, remaining,
+ "fh buffer contains: %d signals, %ld bytes\n",
card->fh_buffer.count,
card->fh_buffer.ptr - card->fh_buffer.buf);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "paused: ");
+ written = scnprintf(p, remaining, "paused: ");
UNIFI_SNPRINTF_RET(p, remaining, written);
for (i = 0; i < sizeof(card->tx_q_paused_flag) / sizeof(card->tx_q_paused_flag[0]); i++)
{
- written = CsrSnprintf(p, remaining, card->tx_q_paused_flag[i]?"1" : "0");
+ written = scnprintf(p, remaining, card->tx_q_paused_flag[i]?"1" : "0");
UNIFI_SNPRINTF_RET(p, remaining, written);
}
- written = CsrSnprintf(p, remaining, "\n");
+ written = scnprintf(p, remaining, "\n");
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining,
+ written = scnprintf(p, remaining,
"fh command q: %u waiting, %u free of %u:\n",
CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_command_queue),
CSR_WIFI_HIP_Q_SLOTS_FREE(&card->fh_command_queue),
UNIFI_SNPRINTF_RET(p, remaining, written);
for (i = 0; i < UNIFI_NO_OF_TX_QS; i++)
{
- written = CsrSnprintf(p, remaining,
+ written = scnprintf(p, remaining,
"fh traffic q[%u]: %u waiting, %u free of %u:\n",
i,
CSR_WIFI_HIP_Q_SLOTS_USED(&card->fh_traffic_queue[i]),
UNIFI_SNPRINTF_RET(p, remaining, written);
}
- written = CsrSnprintf(p, remaining, "fh data slots free: %u\n",
+ written = scnprintf(p, remaining, "fh data slots free: %u\n",
card->from_host_data?CardGetFreeFromHostDataSlots(card) : 0);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "From host data slots:");
+ written = scnprintf(p, remaining, "From host data slots:");
UNIFI_SNPRINTF_RET(p, remaining, written);
n = card->config_data.num_fromhost_data_slots;
for (i = 0; i < n && card->from_host_data; i++)
{
- written = CsrSnprintf(p, remaining, " %u",
+ written = scnprintf(p, remaining, " %u",
(u16)card->from_host_data[i].bd.data_length);
UNIFI_SNPRINTF_RET(p, remaining, written);
}
- written = CsrSnprintf(p, remaining, "\n");
+ written = scnprintf(p, remaining, "\n");
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "To host data slots:");
+ written = scnprintf(p, remaining, "To host data slots:");
UNIFI_SNPRINTF_RET(p, remaining, written);
n = card->config_data.num_tohost_data_slots;
for (i = 0; i < n && card->to_host_data; i++)
{
- written = CsrSnprintf(p, remaining, " %u",
+ written = scnprintf(p, remaining, " %u",
(u16)card->to_host_data[i].data_length);
UNIFI_SNPRINTF_RET(p, remaining, written);
}
- written = CsrSnprintf(p, remaining, "\n");
+ written = scnprintf(p, remaining, "\n");
UNIFI_SNPRINTF_RET(p, remaining, written);
#ifdef CSR_UNSAFE_SDIO_ACCESS
- written = CsrSnprintf(p, remaining, "Host State: %s\n", states[card->host_state]);
+ written = scnprintf(p, remaining, "Host State: %s\n", states[card->host_state]);
UNIFI_SNPRINTF_RET(p, remaining, written);
r = unifi_check_io_status(card, &iostate);
if (iostate == 1)
{
- written = CsrSnprintf(p, remaining, "I/O Check: F1 disabled\n");
+ written = scnprintf(p, remaining, "I/O Check: F1 disabled\n");
UNIFI_SNPRINTF_RET(p, remaining, written);
}
else
{
if (iostate == 1)
{
- written = CsrSnprintf(p, remaining, "I/O Check: pending interrupt\n");
+ written = scnprintf(p, remaining, "I/O Check: pending interrupt\n");
UNIFI_SNPRINTF_RET(p, remaining, written);
}
- written = CsrSnprintf(p, remaining, "BH reason interrupt = %d\n",
+ written = scnprintf(p, remaining, "BH reason interrupt = %d\n",
card->bh_reason_unifi);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "BH reason host = %d\n",
+ written = scnprintf(p, remaining, "BH reason host = %d\n",
card->bh_reason_host);
UNIFI_SNPRINTF_RET(p, remaining, written);
r = unifi_read_8_or_16(card, card->sdio_ctrl_addr + 2, &b);
if ((r == CSR_RESULT_SUCCESS) && (!(b & 0x80)))
{
- written = CsrSnprintf(p, remaining, "fhsr: %u (driver thinks is %u)\n",
+ written = scnprintf(p, remaining, "fhsr: %u (driver thinks is %u)\n",
b, card->from_host_signals_r);
UNIFI_SNPRINTF_RET(p, remaining, written);
break;
}
}
iostate = unifi_read_shared_count(card, card->sdio_ctrl_addr + 4);
- written = CsrSnprintf(p, remaining, "thsw: %u (driver thinks is %u)\n",
+ written = scnprintf(p, remaining, "thsw: %u (driver thinks is %u)\n",
iostate, card->to_host_signals_w);
UNIFI_SNPRINTF_RET(p, remaining, written);
}
#endif
- written = CsrSnprintf(p, remaining, "\nStats:\n");
+ written = scnprintf(p, remaining, "\nStats:\n");
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "Total SDIO bytes: R=%lu W=%lu\n",
+ written = scnprintf(p, remaining, "Total SDIO bytes: R=%u W=%u\n",
card->sdio_bytes_read, card->sdio_bytes_written);
UNIFI_SNPRINTF_RET(p, remaining, written);
- written = CsrSnprintf(p, remaining, "Interrupts generated on card: %lu\n",
+ written = scnprintf(p, remaining, "Interrupts generated on card: %u\n",
card->unifi_interrupt_seq);
UNIFI_SNPRINTF_RET(p, remaining, written);
#include "csr_framework_ext.h" /* from the synergy porting folder */
#include "csr_sdio.h" /* from the synergy porting folder */
#include "csr_macro.h" /* from the synergy porting folder */
-#include "csr_formatted_io.h" /* from the synergy gsp folder */
#include "csr_wifi_result.h"
/* Utility MACROS. Note that UNIFI_MAC_ADDRESS_CMP returns TRUE on success */
* ---------------------------------------------------------------------------
*/
-
-
/*
* Porting Notes:
* Part of this file contains an example for how to glue the OS layer
#include <linux/poll.h>
#include <asm/uaccess.h>
#include <linux/jiffies.h>
+#include <linux/version.h>
#include "csr_wifi_hip_unifiversion.h"
#include "unifi_priv.h"
int uf_release_firmware(unifi_priv_t *priv, struct dlpriv *to_free)
{
if (to_free != NULL) {
- if (to_free->fw_desc != NULL) {
- release_firmware((const struct firmware *)to_free->fw_desc);
- }
+ release_firmware((const struct firmware *)to_free->fw_desc);
to_free->fw_desc = NULL;
to_free->dl_data = NULL;
to_free->dl_len = 0;
* ---------------------------------------------------------------------------
*/
#include <linux/proc_fs.h>
+#include <linux/version.h>
#include "csr_wifi_hip_unifi.h"
#include "csr_wifi_hip_unifiversion.h"
#include "unifiio.h"
#include "unifi_priv.h"
-
/*
* Array of pointers to context structs for unifi devices that are present.
* The index in the array corresponds to the wlan interface number
/*
* We use the slot number as unifi device index.
*/
- snprintf(priv->proc_entry_name, 64, "driver/unifi%d", priv->instance);
+ scnprintf(priv->proc_entry_name, 64, "driver/unifi%d", priv->instance);
/*
* The following complex casting is in place in order to eliminate 64-bit compilation warning
* "cast to/from pointer from/to integer of different size"
orig_p = p;
- written = CsrSnprintf(p, remain, "UniFi SDIO Driver: %s %s %s\n",
+ written = scnprintf(p, remain, "UniFi SDIO Driver: %s %s %s\n",
CSR_WIFI_VERSION, __DATE__, __TIME__);
UNIFI_SNPRINTF_RET(p, remain, written);
#ifdef CSR_SME_USERSPACE
- written = CsrSnprintf(p, remain, "SME: CSR userspace ");
+ written = scnprintf(p, remain, "SME: CSR userspace ");
UNIFI_SNPRINTF_RET(p, remain, written);
#ifdef CSR_SUPPORT_WEXT
- written = CsrSnprintf(p, remain, "with WEXT support\n");
+ written = scnprintf(p, remain, "with WEXT support\n");
#else
- written = CsrSnprintf(p, remain, "\n");
+ written = scnprintf(p, remain, "\n");
#endif /* CSR_SUPPORT_WEXT */
UNIFI_SNPRINTF_RET(p, remain, written);
#endif /* CSR_SME_USERSPACE */
#ifdef CSR_NATIVE_LINUX
- written = CsrSnprintf(p, remain, "SME: native\n");
+ written = scnprintf(p, remain, "SME: native\n");
UNIFI_SNPRINTF_RET(p, remain, written);
#endif
#ifdef CSR_SUPPORT_SME
- written = CsrSnprintf(p, remain,
- "Firmware (ROM) build:%lu, Patch:%lu\n",
+ written = scnprintf(p, remain,
+ "Firmware (ROM) build:%u, Patch:%u\n",
priv->card_info.fw_build,
priv->sme_versions.firmwarePatch);
UNIFI_SNPRINTF_RET(p, remain, written);
#endif
p += unifi_print_status(priv->card, p, &remain);
- written = CsrSnprintf(p, remain, "Last dbg str: %s\n",
+ written = scnprintf(p, remain, "Last dbg str: %s\n",
priv->last_debug_string);
UNIFI_SNPRINTF_RET(p, remain, written);
- written = CsrSnprintf(p, remain, "Last dbg16:");
+ written = scnprintf(p, remain, "Last dbg16:");
UNIFI_SNPRINTF_RET(p, remain, written);
for (i = 0; i < 8; i++) {
- written = CsrSnprintf(p, remain, " %04X",
+ written = scnprintf(p, remain, " %04X",
priv->last_debug_word16[i]);
UNIFI_SNPRINTF_RET(p, remain, written);
}
- written = CsrSnprintf(p, remain, "\n");
+ written = scnprintf(p, remain, "\n");
UNIFI_SNPRINTF_RET(p, remain, written);
- written = CsrSnprintf(p, remain, " ");
+ written = scnprintf(p, remain, " ");
UNIFI_SNPRINTF_RET(p, remain, written);
for (; i < 16; i++) {
- written = CsrSnprintf(p, remain, " %04X",
+ written = scnprintf(p, remain, " %04X",
priv->last_debug_word16[i]);
UNIFI_SNPRINTF_RET(p, remain, written);
}
- written = CsrSnprintf(p, remain, "\n");
+ written = scnprintf(p, remain, "\n");
UNIFI_SNPRINTF_RET(p, remain, written);
*start = page;
* ---------------------------------------------------------------------------
*/
+#include <linux/version.h>
#include "unifi_priv.h"
#ifdef UNIFI_SNIFF_ARPHRD
#define ETH_P_80211_RAW ETH_P_ALL
#endif
-
-
/*
* ---------------------------------------------------------------------------
* uf_start_sniff
* ---------------------------------------------------------------------------
*/
-
/*
* Porting Notes:
* This file implements the data plane of the UniFi linux driver.
#include <linux/etherdevice.h>
#include <linux/mutex.h>
#include <linux/semaphore.h>
-
+#include <linux/version.h>
#include <linux/vmalloc.h>
#include "csr_wifi_hip_unifi.h"
#include "csr_wifi_hip_conversions.h"
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/gfp.h>
-
+#include <linux/version.h>
#include <linux/mmc/core.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
* Status of the removal.
* ---------------------------------------------------------------------------
*/
-int
-csr_sdio_linux_remove_irq(CsrSdioFunction *function)
+int csr_sdio_linux_remove_irq(CsrSdioFunction *function)
{
- struct sdio_func *func = (struct sdio_func *)function->priv;
- int r;
+ struct sdio_func *func = (struct sdio_func *)function->priv;
+ int r;
- unifi_trace(NULL, UDBG1, "csr_sdio_linux_remove_irq\n");
+ unifi_trace(NULL, UDBG1, "csr_sdio_linux_remove_irq\n");
- sdio_claim_host(func);
- r = sdio_release_irq(func);
- sdio_release_host(func);
+ sdio_claim_host(func);
+ r = sdio_release_irq(func);
+ sdio_release_host(func);
- return r;
+ return r;
} /* csr_sdio_linux_remove_irq() */
* Status of the removal.
* ---------------------------------------------------------------------------
*/
-int
-csr_sdio_linux_install_irq(CsrSdioFunction *function)
+int csr_sdio_linux_install_irq(CsrSdioFunction *function)
{
- struct sdio_func *func = (struct sdio_func *)function->priv;
- int r;
+ struct sdio_func *func = (struct sdio_func *)function->priv;
+ int r;
- unifi_trace(NULL, UDBG1, "csr_sdio_linux_install_irq\n");
+ unifi_trace(NULL, UDBG1, "csr_sdio_linux_install_irq\n");
- /* Register our interrupt handle */
- sdio_claim_host(func);
- r = sdio_claim_irq(func, uf_glue_sdio_int_handler);
- sdio_release_host(func);
+ /* Register our interrupt handle */
+ sdio_claim_host(func);
+ r = sdio_claim_irq(func, uf_glue_sdio_int_handler);
+ sdio_release_host(func);
- /* If the interrupt was installed earlier, is fine */
- if (r == -EBUSY) {
- r = 0;
- }
+ /* If the interrupt was installed earlier, is fine */
+ if (r == -EBUSY)
+ r = 0;
- return r;
+ return r;
} /* csr_sdio_linux_install_irq() */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
*/
#include <linux/netdevice.h>
-
+#include <linux/version.h>
#include "unifi_priv.h"
#include "csr_wifi_hip_unifi.h"
#include "csr_wifi_hip_conversions.h"
* ---------------------------------------------------------------------------
*/
+#include <linux/version.h>
#include "csr_wifi_hip_unifiversion.h"
#include "unifi_priv.h"
#include "csr_wifi_hip_conversions.h"
#include "csr_wifi_sme_sef.h"
#endif
-
/*
* This file implements the SME SYS API and contains the following functions:
* CsrWifiRouterCtrlMediaStatusReqHandler()
memcpy(sme_key.address.a, ext->addr.sa_data, ETH_ALEN);
if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
- unifi_trace(priv, UDBG5, "RSC first 6 bytes = %02X:%02X:%02X:%02X:%02X:%02X\n",
- ext->rx_seq[0], ext->rx_seq[1], ext->rx_seq[2], ext->rx_seq[3], ext->rx_seq[4], ext->rx_seq[5]);
+ unifi_trace(priv, UDBG5, "RSC first 6 bytes = %*phC\n",
+ 6, ext->rx_seq);
/* memcpy((u8*)(&sme_key.keyRsc), ext->rx_seq, 8); */
sme_key.keyRsc[0] = ext->rx_seq[1] << 8 | ext->rx_seq[0];
*
* ***************************************************************************
*/
+#include <linux/version.h>
#include "csr_wifi_hip_unifi.h"
#include "csr_wifi_hip_conversions.h"
#include "unifi_priv.h"
* ---------------------------------------------------------------------------
*/
-
+#include <linux/version.h>
#include <linux/types.h>
#include <linux/etherdevice.h>
#include <linux/vmalloc.h>
#define __LINUX_UNIFI_WEXT_H__ 1
#include <linux/kernel.h>
+#include <linux/version.h>
#include <net/iw_handler.h>
#include "csr_wifi_sme_prim.h"
union iwreq_data wrqu;
char buf[128];
- sprintf(buf,
- "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=%02x:%02x:%02x:%02x:%02x:%02x)",
- key_idx, (key_type == CSR_GROUP) ? "broad" : "uni",
- macaddr[0], macaddr[1], macaddr[2],
- macaddr[3], macaddr[4], macaddr[5]);
+ sprintf(buf,
+ "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=%pM)",
+ key_idx, (key_type == CSR_GROUP) ? "broad" : "uni", macaddr);
memset(&wrqu, 0, sizeof(wrqu));
wrqu.data.length = strlen(buf);
wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
}
ret = usb_control_msg(ft1000dev->dev, pipe, request, requesttype,
- value, index, data, size, LARGE_TIMEOUT);
+ value, index, data, size, timeout);
if (ret > 0)
ret = 0;
nRegIndx,
Data,
2,
- LARGE_TIMEOUT);
+ USB_CTRL_GET_TIMEOUT);
return ret;
}
nRegIndx,
NULL,
0,
- LARGE_TIMEOUT);
+ USB_CTRL_SET_TIMEOUT);
return ret;
}
indx,
buffer,
cnt,
- LARGE_TIMEOUT);
+ USB_CTRL_GET_TIMEOUT);
return ret;
}
indx,
buffer,
cnt,
- LARGE_TIMEOUT);
+ USB_CTRL_SET_TIMEOUT);
return ret;
}
indx,
buffer,
2,
- LARGE_TIMEOUT);
+ USB_CTRL_GET_TIMEOUT);
return ret;
}
indx,
NULL,
0,
- LARGE_TIMEOUT);
+ USB_CTRL_SET_TIMEOUT);
return ret;
}
#define FT1000_STATUS_CLOSING 0x01
-#define LARGE_TIMEOUT 5000
-
#define DSPBCMSGID 0x10
/* Electrabuzz specific DPRAM mapping */
{
struct sdio_tx *t = NULL;
- t = kmalloc(sizeof(*t), GFP_ATOMIC);
+ t = kzalloc(sizeof(*t), GFP_ATOMIC);
if (t == NULL)
goto out;
- memset(t, 0, sizeof(*t));
-
t->buf = kmalloc(TX_BUF_SIZE, GFP_ATOMIC);
if (t->buf == NULL)
goto out;
phy_dev->rcv_func = gdm_sdio_receive;
ret = init_sdio(sdev);
- if (sdev < 0)
+ if (ret < 0)
goto out;
sdev->func = func;
{
struct usb_tx *t = NULL;
- t = kmalloc(sizeof(*t), GFP_ATOMIC);
+ t = kzalloc(sizeof(*t), GFP_ATOMIC);
if (t == NULL)
goto out;
- memset(t, 0, sizeof(*t));
-
t->urb = usb_alloc_urb(0, GFP_ATOMIC);
t->buf = kmalloc(TX_BUF_SIZE, GFP_ATOMIC);
if (t->urb == NULL || t->buf == NULL)
if (!wm_event.ref_cnt) {
wm_event.sock = netlink_init(NETLINK_WIMAX,
gdm_wimax_event_rcv);
- if (wm_event.sock)
- wm_event.ref_cnt++;
- INIT_LIST_HEAD(&wm_event.evtq);
- INIT_LIST_HEAD(&wm_event.freeq);
- INIT_WORK(&wm_event.ws, __gdm_wimax_event_send);
- spin_lock_init(&wm_event.evt_lock);
+ if (wm_event.sock) {
+ INIT_LIST_HEAD(&wm_event.evtq);
+ INIT_LIST_HEAD(&wm_event.freeq);
+ INIT_WORK(&wm_event.ws, __gdm_wimax_event_send);
+ spin_lock_init(&wm_event.evt_lock);
+ }
+ }
+
+ if (wm_event.sock) {
+ wm_event.ref_cnt++;
return 0;
}
print2byte(*(uint16_t *)(data + channels[k].location),
&channels[k]);
break;
+ case 4:
+ if (!channels[k].is_signed) {
+ uint32_t val = *(uint32_t *)
+ (data + channels[k].location);
+ printf("%05f ", ((float)val +
+ channels[k].offset)*
+ channels[k].scale);
+
+ }
+ break;
case 8:
if (channels[k].is_signed) {
int64_t val = *(int64_t *)
return -EINVAL;
}
-static struct iio_chan_spec adis16201_channels[] = {
+static const struct iio_chan_spec adis16201_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1,
}
}
-static struct iio_chan_spec adis16203_channels[] = {
+static const struct iio_chan_spec adis16203_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1,
return -EINVAL;
}
-static struct iio_chan_spec adis16204_channels[] = {
+static const struct iio_chan_spec adis16204_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1, /* Note was not previously indexed */
return -EINVAL;
}
-static struct iio_chan_spec adis16209_channels[] = {
+static const struct iio_chan_spec adis16209_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1,
loff_t off,
size_t count)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj));
return adis16220_capture_buffer_read(indio_dev, buf,
off, count,
char *buf, loff_t off,
size_t count)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj));
return adis16220_capture_buffer_read(indio_dev, buf,
off, count,
char *buf, loff_t off,
size_t count)
{
- struct device *dev = container_of(kobj, struct device, kobj);
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct iio_dev *indio_dev = dev_to_iio_dev(kobj_to_dev(kobj));
return adis16220_capture_buffer_read(indio_dev, buf,
off, count,
return -EINVAL;
}
-static struct iio_chan_spec adis16240_channels[] = {
+static const struct iio_chan_spec adis16240_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1,
.address = KXSD9_REG_##axis, \
}
-static struct iio_chan_spec kxsd9_channels[] = {
+static const struct iio_chan_spec kxsd9_channels[] = {
KXSD9_ACCEL_CHAN(X), KXSD9_ACCEL_CHAN(Y), KXSD9_ACCEL_CHAN(Z),
{
.type = IIO_VOLTAGE,
.event_mask = LIS3L02DQ_EVENT_MASK, \
}
-static struct iio_chan_spec lis3l02dq_channels[] = {
+static const struct iio_chan_spec lis3l02dq_channels[] = {
LIS3L02DQ_CHAN(0, IIO_MOD_X),
LIS3L02DQ_CHAN(1, IIO_MOD_Y),
LIS3L02DQ_CHAN(2, IIO_MOD_Z),
.event_mask = SCA3000_EVENT_MASK, \
}
-static struct iio_chan_spec sca3000_channels[] = {
+static const struct iio_chan_spec sca3000_channels[] = {
SCA3000_CHAN(0, IIO_MOD_X),
SCA3000_CHAN(1, IIO_MOD_Y),
SCA3000_CHAN(2, IIO_MOD_Z),
activate only one via device tree selection. Provides direct access
via sysfs.
+config MXS_LRADC
+ tristate "Freescale i.MX28 LRADC"
+ depends on ARCH_MXS
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for i.MX28 LRADC convertor
+ built into these chips.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mxs-lradc.
+
config SPEAR_ADC
tristate "ST SPEAr ADC"
depends on PLAT_SPEAR
obj-$(CONFIG_ADT7410) += adt7410.o
obj-$(CONFIG_AD7280) += ad7280a.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
+obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o
obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
.scan_index = _si, \
.scan_type = IIO_ST('u', 24, 32, 0)}
-static struct iio_chan_spec ad7192_channels[] = {
+static const struct iio_chan_spec ad7192_channels[] = {
AD7192_CHAN_DIFF(1, 2, NULL, AD7192_CH_AIN1P_AIN2M, 0),
AD7192_CHAN_DIFF(3, 4, NULL, AD7192_CH_AIN3P_AIN4M, 1),
AD7192_CHAN_TEMP(0, AD7192_CH_TEMP, 2),
}, \
}
-static struct iio_chan_spec ad7298_channels[] = {
+static const struct iio_chan_spec ad7298_channels[] = {
{
.type = IIO_TEMP,
.indexed = 1,
struct ad7606_chip_info {
const char *name;
u16 int_vref_mv;
- struct iio_chan_spec *channels;
+ const struct iio_chan_spec *channels;
unsigned num_channels;
};
.scan_type = IIO_ST('s', 16, 16, 0), \
}
-static struct iio_chan_spec ad7606_8_channels[] = {
+static const struct iio_chan_spec ad7606_8_channels[] = {
AD7606_CHANNEL(0),
AD7606_CHANNEL(1),
AD7606_CHANNEL(2),
IIO_CHAN_SOFT_TIMESTAMP(8),
};
-static struct iio_chan_spec ad7606_6_channels[] = {
+static const struct iio_chan_spec ad7606_6_channels[] = {
AD7606_CHANNEL(0),
AD7606_CHANNEL(1),
AD7606_CHANNEL(2),
IIO_CHAN_SOFT_TIMESTAMP(6),
};
-static struct iio_chan_spec ad7606_4_channels[] = {
+static const struct iio_chan_spec ad7606_4_channels[] = {
AD7606_CHANNEL(0),
AD7606_CHANNEL(1),
AD7606_CHANNEL(2),
.scan_index = _index, \
}
-static struct iio_chan_spec lpc32xx_adc_iio_channels[] = {
+static const struct iio_chan_spec lpc32xx_adc_iio_channels[] = {
LPC32XX_ADC_CHANNEL(0),
LPC32XX_ADC_CHANNEL(1),
LPC32XX_ADC_CHANNEL(2),
*/
struct max1363_chip_info {
const struct iio_info *info;
- struct iio_chan_spec *channels;
+ const struct iio_chan_spec *channels;
int num_channels;
const enum max1363_modes *mode_list;
enum max1363_modes default_mode;
IIO_CHAN_SOFT_TIMESTAMP(8) \
}
-static struct iio_chan_spec max1036_channels[] = MAX1363_4X_CHANS(8, 0);
-static struct iio_chan_spec max1136_channels[] = MAX1363_4X_CHANS(10, 0);
-static struct iio_chan_spec max1236_channels[] = MAX1363_4X_CHANS(12, 0);
-static struct iio_chan_spec max1361_channels[] =
+static const struct iio_chan_spec max1036_channels[] = MAX1363_4X_CHANS(8, 0);
+static const struct iio_chan_spec max1136_channels[] = MAX1363_4X_CHANS(10, 0);
+static const struct iio_chan_spec max1236_channels[] = MAX1363_4X_CHANS(12, 0);
+static const struct iio_chan_spec max1361_channels[] =
MAX1363_4X_CHANS(10, MAX1363_EV_M);
-static struct iio_chan_spec max1363_channels[] =
+static const struct iio_chan_spec max1363_channels[] =
MAX1363_4X_CHANS(12, MAX1363_EV_M);
/* Applies to max1236, max1237 */
MAX1363_CHAN_B(11, 10, d11m10, 23, bits, 0), \
IIO_CHAN_SOFT_TIMESTAMP(24) \
}
-static struct iio_chan_spec max1038_channels[] = MAX1363_12X_CHANS(8);
-static struct iio_chan_spec max1138_channels[] = MAX1363_12X_CHANS(10);
-static struct iio_chan_spec max1238_channels[] = MAX1363_12X_CHANS(12);
+static const struct iio_chan_spec max1038_channels[] = MAX1363_12X_CHANS(8);
+static const struct iio_chan_spec max1138_channels[] = MAX1363_12X_CHANS(10);
+static const struct iio_chan_spec max1238_channels[] = MAX1363_12X_CHANS(12);
static const enum max1363_modes max11607_mode_list[] = {
_s0, _s1, _s2, _s3,
MAX1363_CHAN_B(7, 6, d7m6, 15, bits, 0), \
IIO_CHAN_SOFT_TIMESTAMP(16) \
}
-static struct iio_chan_spec max11602_channels[] = MAX1363_8X_CHANS(8);
-static struct iio_chan_spec max11608_channels[] = MAX1363_8X_CHANS(10);
-static struct iio_chan_spec max11614_channels[] = MAX1363_8X_CHANS(12);
+static const struct iio_chan_spec max11602_channels[] = MAX1363_8X_CHANS(8);
+static const struct iio_chan_spec max11608_channels[] = MAX1363_8X_CHANS(10);
+static const struct iio_chan_spec max11614_channels[] = MAX1363_8X_CHANS(12);
static const enum max1363_modes max11644_mode_list[] = {
_s0, _s1, s0to1, d0m1, d1m0,
IIO_CHAN_SOFT_TIMESTAMP(4) \
}
-static struct iio_chan_spec max11646_channels[] = MAX1363_2X_CHANS(10);
-static struct iio_chan_spec max11644_channels[] = MAX1363_2X_CHANS(12);
+static const struct iio_chan_spec max11646_channels[] = MAX1363_2X_CHANS(10);
+static const struct iio_chan_spec max11644_channels[] = MAX1363_2X_CHANS(12);
enum { max1361,
max1362,
--- /dev/null
+/*
+ * Freescale i.MX28 LRADC driver
+ *
+ * Copyright (c) 2012 DENX Software Engineering, GmbH.
+ * Marek Vasut <marex@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/sysfs.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/stmp_device.h>
+#include <linux/bitops.h>
+#include <linux/completion.h>
+
+#include <mach/mxs.h>
+#include <mach/common.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define DRIVER_NAME "mxs-lradc"
+
+#define LRADC_MAX_DELAY_CHANS 4
+#define LRADC_MAX_MAPPED_CHANS 8
+#define LRADC_MAX_TOTAL_CHANS 16
+
+#define LRADC_DELAY_TIMER_HZ 2000
+
+/*
+ * Make this runtime configurable if necessary. Currently, if the buffered mode
+ * is enabled, the LRADC takes LRADC_DELAY_TIMER_LOOP samples of data before
+ * triggering IRQ. The sampling happens every (LRADC_DELAY_TIMER_PER / 2000)
+ * seconds. The result is that the samples arrive every 500mS.
+ */
+#define LRADC_DELAY_TIMER_PER 200
+#define LRADC_DELAY_TIMER_LOOP 5
+
+static const char * const mxs_lradc_irq_name[] = {
+ "mxs-lradc-touchscreen",
+ "mxs-lradc-thresh0",
+ "mxs-lradc-thresh1",
+ "mxs-lradc-channel0",
+ "mxs-lradc-channel1",
+ "mxs-lradc-channel2",
+ "mxs-lradc-channel3",
+ "mxs-lradc-channel4",
+ "mxs-lradc-channel5",
+ "mxs-lradc-channel6",
+ "mxs-lradc-channel7",
+ "mxs-lradc-button0",
+ "mxs-lradc-button1",
+};
+
+struct mxs_lradc_chan {
+ uint8_t slot;
+ uint8_t flags;
+};
+
+struct mxs_lradc {
+ struct device *dev;
+ void __iomem *base;
+ int irq[13];
+
+ uint32_t *buffer;
+ struct iio_trigger *trig;
+
+ struct mutex lock;
+
+ uint8_t enable;
+
+ struct completion completion;
+};
+
+#define LRADC_CTRL0 0x00
+#define LRADC_CTRL0_TOUCH_DETECT_ENABLE (1 << 23)
+#define LRADC_CTRL0_TOUCH_SCREEN_TYPE (1 << 22)
+
+#define LRADC_CTRL1 0x10
+#define LRADC_CTRL1_LRADC_IRQ(n) (1 << (n))
+#define LRADC_CTRL1_LRADC_IRQ_MASK 0x1fff
+#define LRADC_CTRL1_LRADC_IRQ_EN(n) (1 << ((n) + 16))
+#define LRADC_CTRL1_LRADC_IRQ_EN_MASK (0x1fff << 16)
+
+#define LRADC_CTRL2 0x20
+#define LRADC_CTRL2_TEMPSENSE_PWD (1 << 15)
+
+#define LRADC_CH(n) (0x50 + (0x10 * (n)))
+#define LRADC_CH_ACCUMULATE (1 << 29)
+#define LRADC_CH_NUM_SAMPLES_MASK (0x1f << 24)
+#define LRADC_CH_NUM_SAMPLES_OFFSET 24
+#define LRADC_CH_VALUE_MASK 0x3ffff
+#define LRADC_CH_VALUE_OFFSET 0
+
+#define LRADC_DELAY(n) (0xd0 + (0x10 * (n)))
+#define LRADC_DELAY_TRIGGER_LRADCS_MASK (0xff << 24)
+#define LRADC_DELAY_TRIGGER_LRADCS_OFFSET 24
+#define LRADC_DELAY_KICK (1 << 20)
+#define LRADC_DELAY_TRIGGER_DELAYS_MASK (0xf << 16)
+#define LRADC_DELAY_TRIGGER_DELAYS_OFFSET 16
+#define LRADC_DELAY_LOOP_COUNT_MASK (0x1f << 11)
+#define LRADC_DELAY_LOOP_COUNT_OFFSET 11
+#define LRADC_DELAY_DELAY_MASK 0x7ff
+#define LRADC_DELAY_DELAY_OFFSET 0
+
+#define LRADC_CTRL4 0x140
+#define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4))
+#define LRADC_CTRL4_LRADCSELECT_OFFSET(n) ((n) * 4)
+
+/*
+ * Raw I/O operations
+ */
+static int mxs_lradc_read_raw(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long m)
+{
+ struct mxs_lradc *lradc = iio_priv(iio_dev);
+ int ret;
+
+ if (m != IIO_CHAN_INFO_RAW)
+ return -EINVAL;
+
+ /* Check for invalid channel */
+ if (chan->channel > LRADC_MAX_TOTAL_CHANS)
+ return -EINVAL;
+
+ /*
+ * See if there is no buffered operation in progess. If there is, simply
+ * bail out. This can be improved to support both buffered and raw IO at
+ * the same time, yet the code becomes horribly complicated. Therefore I
+ * applied KISS principle here.
+ */
+ ret = mutex_trylock(&lradc->lock);
+ if (!ret)
+ return -EBUSY;
+
+ INIT_COMPLETION(lradc->completion);
+
+ /*
+ * No buffered operation in progress, map the channel and trigger it.
+ * Virtual channel 0 is always used here as the others are always not
+ * used if doing raw sampling.
+ */
+ writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
+ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+ writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
+
+ writel(chan->channel, lradc->base + LRADC_CTRL4);
+ writel(0, lradc->base + LRADC_CH(0));
+
+ /* Enable the IRQ and start sampling the channel. */
+ writel(LRADC_CTRL1_LRADC_IRQ_EN(0),
+ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
+ writel(1 << 0, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_SET);
+
+ /* Wait for completion on the channel, 1 second max. */
+ ret = wait_for_completion_killable_timeout(&lradc->completion, HZ);
+ if (!ret)
+ ret = -ETIMEDOUT;
+ if (ret < 0)
+ goto err;
+
+ /* Read the data. */
+ *val = readl(lradc->base + LRADC_CH(0)) & LRADC_CH_VALUE_MASK;
+ ret = IIO_VAL_INT;
+
+err:
+ writel(LRADC_CTRL1_LRADC_IRQ_EN(0),
+ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+
+ mutex_unlock(&lradc->lock);
+
+ return ret;
+}
+
+static const struct iio_info mxs_lradc_iio_info = {
+ .driver_module = THIS_MODULE,
+ .read_raw = mxs_lradc_read_raw,
+};
+
+/*
+ * IRQ Handling
+ */
+static irqreturn_t mxs_lradc_handle_irq(int irq, void *data)
+{
+ struct iio_dev *iio = data;
+ struct mxs_lradc *lradc = iio_priv(iio);
+ unsigned long reg = readl(lradc->base + LRADC_CTRL1);
+
+ if (!(reg & LRADC_CTRL1_LRADC_IRQ_MASK))
+ return IRQ_NONE;
+
+ /*
+ * Touchscreen IRQ handling code shall probably have priority
+ * and therefore shall be placed here.
+ */
+
+ if (iio_buffer_enabled(iio))
+ iio_trigger_poll(iio->trig, iio_get_time_ns());
+ else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
+ complete(&lradc->completion);
+
+ writel(reg & LRADC_CTRL1_LRADC_IRQ_MASK,
+ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Trigger handling
+ */
+static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *iio = pf->indio_dev;
+ struct mxs_lradc *lradc = iio_priv(iio);
+ struct iio_buffer *buffer = iio->buffer;
+ const uint32_t chan_value = LRADC_CH_ACCUMULATE |
+ ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
+ int i, j = 0;
+
+ for_each_set_bit(i, iio->active_scan_mask, iio->masklength) {
+ lradc->buffer[j] = readl(lradc->base + LRADC_CH(j));
+ writel(chan_value, lradc->base + LRADC_CH(j));
+ lradc->buffer[j] &= LRADC_CH_VALUE_MASK;
+ lradc->buffer[j] /= LRADC_DELAY_TIMER_LOOP;
+ j++;
+ }
+
+ if (iio->scan_timestamp) {
+ s64 *timestamp = (s64 *)((u8 *)lradc->buffer +
+ ALIGN(j, sizeof(s64)));
+ *timestamp = pf->timestamp;
+ }
+
+ iio_push_to_buffer(buffer, (u8 *)lradc->buffer, pf->timestamp);
+
+ iio_trigger_notify_done(iio->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int mxs_lradc_configure_trigger(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *iio = trig->private_data;
+ struct mxs_lradc *lradc = iio_priv(iio);
+ const uint32_t st = state ? STMP_OFFSET_REG_SET : STMP_OFFSET_REG_CLR;
+
+ writel(LRADC_DELAY_KICK, lradc->base + LRADC_DELAY(0) + st);
+
+ return 0;
+}
+
+static const struct iio_trigger_ops mxs_lradc_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = &mxs_lradc_configure_trigger,
+};
+
+static int mxs_lradc_trigger_init(struct iio_dev *iio)
+{
+ int ret;
+ struct iio_trigger *trig;
+
+ trig = iio_trigger_alloc("%s-dev%i", iio->name, iio->id);
+ if (trig == NULL)
+ return -ENOMEM;
+
+ trig->dev.parent = iio->dev.parent;
+ trig->private_data = iio;
+ trig->ops = &mxs_lradc_trigger_ops;
+
+ ret = iio_trigger_register(trig);
+ if (ret) {
+ iio_trigger_free(trig);
+ return ret;
+ }
+
+ iio->trig = trig;
+
+ return 0;
+}
+
+static void mxs_lradc_trigger_remove(struct iio_dev *iio)
+{
+ iio_trigger_unregister(iio->trig);
+ iio_trigger_free(iio->trig);
+}
+
+static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
+{
+ struct mxs_lradc *lradc = iio_priv(iio);
+ struct iio_buffer *buffer = iio->buffer;
+ int ret = 0, chan, ofs = 0, enable = 0;
+ uint32_t ctrl4 = 0;
+ uint32_t ctrl1_irq = 0;
+ const uint32_t chan_value = LRADC_CH_ACCUMULATE |
+ ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
+ const int len = bitmap_weight(buffer->scan_mask, LRADC_MAX_TOTAL_CHANS);
+
+ if (!len)
+ return -EINVAL;
+
+ /*
+ * Lock the driver so raw access can not be done during buffered
+ * operation. This simplifies the code a lot.
+ */
+ ret = mutex_trylock(&lradc->lock);
+ if (!ret)
+ return -EBUSY;
+
+ lradc->buffer = kmalloc(len * sizeof(*lradc->buffer), GFP_KERNEL);
+ if (!lradc->buffer) {
+ ret = -ENOMEM;
+ goto err_mem;
+ }
+
+ ret = iio_sw_buffer_preenable(iio);
+ if (ret < 0)
+ goto err_buf;
+
+ writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
+ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+ writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
+
+ for_each_set_bit(chan, buffer->scan_mask, LRADC_MAX_TOTAL_CHANS) {
+ ctrl4 |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs);
+ ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs);
+ writel(chan_value, lradc->base + LRADC_CH(ofs));
+ enable |= 1 << ofs;
+ ofs++;
+ };
+
+ writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK,
+ lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
+
+ writel(ctrl4, lradc->base + LRADC_CTRL4);
+ writel(ctrl1_irq, lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_SET);
+
+ writel(enable << LRADC_DELAY_TRIGGER_LRADCS_OFFSET,
+ lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_SET);
+
+ return 0;
+
+err_buf:
+ kfree(lradc->buffer);
+err_mem:
+ mutex_unlock(&lradc->lock);
+ return ret;
+}
+
+static int mxs_lradc_buffer_postdisable(struct iio_dev *iio)
+{
+ struct mxs_lradc *lradc = iio_priv(iio);
+
+ writel(LRADC_DELAY_TRIGGER_LRADCS_MASK | LRADC_DELAY_KICK,
+ lradc->base + LRADC_DELAY(0) + STMP_OFFSET_REG_CLR);
+
+ writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
+ writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
+ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+
+ kfree(lradc->buffer);
+ mutex_unlock(&lradc->lock);
+
+ return 0;
+}
+
+static bool mxs_lradc_validate_scan_mask(struct iio_dev *iio,
+ const unsigned long *mask)
+{
+ const int mw = bitmap_weight(mask, iio->masklength);
+
+ return mw <= LRADC_MAX_MAPPED_CHANS;
+}
+
+static const struct iio_buffer_setup_ops mxs_lradc_buffer_ops = {
+ .preenable = &mxs_lradc_buffer_preenable,
+ .postenable = &iio_triggered_buffer_postenable,
+ .predisable = &iio_triggered_buffer_predisable,
+ .postdisable = &mxs_lradc_buffer_postdisable,
+ .validate_scan_mask = &mxs_lradc_validate_scan_mask,
+};
+
+/*
+ * Driver initialization
+ */
+
+#define MXS_ADC_CHAN(idx, chan_type) { \
+ .type = (chan_type), \
+ .indexed = 1, \
+ .scan_index = (idx), \
+ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \
+ .channel = (idx), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 18, \
+ .storagebits = 32, \
+ }, \
+}
+
+static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
+ MXS_ADC_CHAN(0, IIO_VOLTAGE),
+ MXS_ADC_CHAN(1, IIO_VOLTAGE),
+ MXS_ADC_CHAN(2, IIO_VOLTAGE),
+ MXS_ADC_CHAN(3, IIO_VOLTAGE),
+ MXS_ADC_CHAN(4, IIO_VOLTAGE),
+ MXS_ADC_CHAN(5, IIO_VOLTAGE),
+ MXS_ADC_CHAN(6, IIO_VOLTAGE),
+ MXS_ADC_CHAN(7, IIO_VOLTAGE), /* VBATT */
+ MXS_ADC_CHAN(8, IIO_TEMP), /* Temp sense 0 */
+ MXS_ADC_CHAN(9, IIO_TEMP), /* Temp sense 1 */
+ MXS_ADC_CHAN(10, IIO_VOLTAGE), /* VDDIO */
+ MXS_ADC_CHAN(11, IIO_VOLTAGE), /* VTH */
+ MXS_ADC_CHAN(12, IIO_VOLTAGE), /* VDDA */
+ MXS_ADC_CHAN(13, IIO_VOLTAGE), /* VDDD */
+ MXS_ADC_CHAN(14, IIO_VOLTAGE), /* VBG */
+ MXS_ADC_CHAN(15, IIO_VOLTAGE), /* VDD5V */
+};
+
+static void mxs_lradc_hw_init(struct mxs_lradc *lradc)
+{
+ int i;
+ const uint32_t cfg =
+ (LRADC_DELAY_TIMER_PER << LRADC_DELAY_DELAY_OFFSET);
+
+ stmp_reset_block(lradc->base);
+
+ for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++)
+ writel(cfg | (1 << (LRADC_DELAY_TRIGGER_DELAYS_OFFSET + i)),
+ lradc->base + LRADC_DELAY(i));
+
+ /* Start internal temperature sensing. */
+ writel(0, lradc->base + LRADC_CTRL2);
+}
+
+static void mxs_lradc_hw_stop(struct mxs_lradc *lradc)
+{
+ int i;
+
+ writel(LRADC_CTRL1_LRADC_IRQ_EN_MASK,
+ lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
+
+ for (i = 0; i < LRADC_MAX_DELAY_CHANS; i++)
+ writel(0, lradc->base + LRADC_DELAY(i));
+}
+
+static int __devinit mxs_lradc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mxs_lradc *lradc;
+ struct iio_dev *iio;
+ struct resource *iores;
+ int ret = 0;
+ int i;
+
+ /* Allocate the IIO device. */
+ iio = iio_device_alloc(sizeof(*lradc));
+ if (!iio) {
+ dev_err(dev, "Failed to allocate IIO device\n");
+ return -ENOMEM;
+ }
+
+ lradc = iio_priv(iio);
+
+ /* Grab the memory area */
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ lradc->dev = &pdev->dev;
+ lradc->base = devm_request_and_ioremap(dev, iores);
+ if (!lradc->base) {
+ ret = -EADDRNOTAVAIL;
+ goto err_addr;
+ }
+
+ /* Grab all IRQ sources */
+ for (i = 0; i < 13; i++) {
+ lradc->irq[i] = platform_get_irq(pdev, i);
+ if (lradc->irq[i] < 0) {
+ ret = -EINVAL;
+ goto err_addr;
+ }
+
+ ret = devm_request_irq(dev, lradc->irq[i],
+ mxs_lradc_handle_irq, 0,
+ mxs_lradc_irq_name[i], iio);
+ if (ret)
+ goto err_addr;
+ }
+
+ platform_set_drvdata(pdev, iio);
+
+ init_completion(&lradc->completion);
+ mutex_init(&lradc->lock);
+
+ iio->name = pdev->name;
+ iio->dev.parent = &pdev->dev;
+ iio->info = &mxs_lradc_iio_info;
+ iio->modes = INDIO_DIRECT_MODE;
+ iio->channels = mxs_lradc_chan_spec;
+ iio->num_channels = ARRAY_SIZE(mxs_lradc_chan_spec);
+
+ ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time,
+ &mxs_lradc_trigger_handler,
+ &mxs_lradc_buffer_ops);
+ if (ret)
+ goto err_addr;
+
+ ret = mxs_lradc_trigger_init(iio);
+ if (ret)
+ goto err_trig;
+
+ /* Register IIO device. */
+ ret = iio_device_register(iio);
+ if (ret) {
+ dev_err(dev, "Failed to register IIO device\n");
+ goto err_dev;
+ }
+
+ /* Configure the hardware. */
+ mxs_lradc_hw_init(lradc);
+
+ return 0;
+
+err_dev:
+ mxs_lradc_trigger_remove(iio);
+err_trig:
+ iio_triggered_buffer_cleanup(iio);
+err_addr:
+ iio_device_free(iio);
+ return ret;
+}
+
+static int __devexit mxs_lradc_remove(struct platform_device *pdev)
+{
+ struct iio_dev *iio = platform_get_drvdata(pdev);
+ struct mxs_lradc *lradc = iio_priv(iio);
+
+ mxs_lradc_hw_stop(lradc);
+
+ iio_device_unregister(iio);
+ iio_triggered_buffer_cleanup(iio);
+ mxs_lradc_trigger_remove(iio);
+ iio_device_free(iio);
+
+ return 0;
+}
+
+static const struct of_device_id mxs_lradc_dt_ids[] = {
+ { .compatible = "fsl,imx28-lradc", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_lradc_dt_ids);
+
+static struct platform_driver mxs_lradc_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = mxs_lradc_dt_ids,
+ },
+ .probe = mxs_lradc_probe,
+ .remove = __devexit_p(mxs_lradc_remove),
+};
+
+module_platform_driver(mxs_lradc_driver);
+
+MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
+MODULE_DESCRIPTION("Freescale i.MX28 LRADC driver");
+MODULE_LICENSE("GPL v2");
}, \
}
-static struct iio_chan_spec spear_adc_iio_channels[] = {
+static const struct iio_chan_spec spear_adc_iio_channels[] = {
SPEAR_ADC_CHAN(0),
SPEAR_ADC_CHAN(1),
SPEAR_ADC_CHAN(2),
.remove = __devexit_p(iio_hwmon_remove),
};
-static int iio_inkern_init(void)
-{
- return platform_driver_register(&iio_hwmon_driver);
-}
-module_init(iio_inkern_init);
-
-static void iio_inkern_exit(void)
-{
- platform_driver_unregister(&iio_hwmon_driver);
-}
-module_exit(iio_inkern_exit);
+module_platform_driver(iio_hwmon_driver);
MODULE_AUTHOR("Jonathan Cameron <jic23@cam.ac.uk>");
MODULE_DESCRIPTION("IIO to hwmon driver");
* This array of structures tells the IIO core about what the device
* actually provides for a given channel.
*/
-static struct iio_chan_spec iio_dummy_channels[] = {
+static const struct iio_chan_spec iio_dummy_channels[] = {
/* indexed ADC channel in_voltage0_raw etc */
{
.type = IIO_VOLTAGE,
.vref_mv = 3300,
};
-static struct iio_chan_spec ad5933_channels[] = {
+static const struct iio_chan_spec ad5933_channels[] = {
{
.type = IIO_TEMP,
.indexed = 1,
}
}
-static struct iio_chan_spec adis16400_channels[] = {
+static const struct iio_chan_spec adis16400_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1,
IIO_CHAN_SOFT_TIMESTAMP(12)
};
-static struct iio_chan_spec adis16350_channels[] = {
+static const struct iio_chan_spec adis16350_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1,
IIO_CHAN_SOFT_TIMESTAMP(11)
};
-static struct iio_chan_spec adis16300_channels[] = {
+static const struct iio_chan_spec adis16300_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1,
u8 *tx;
u8 *rx;
struct mutex buf_lock;
- struct iio_chan_spec *ade7758_ring_channels;
+ const struct iio_chan_spec *ade7758_ring_channels;
struct spi_transfer ring_xfer[4];
struct spi_message ring_msg;
/*
.attrs = ade7758_attributes,
};
-static struct iio_chan_spec ade7758_channels[] = {
+static const struct iio_chan_spec ade7758_channels[] = {
{
.type = IIO_VOLTAGE,
.indexed = 1,
AD2S1210_REG_LOT_LOW_THRD);
-static struct iio_chan_spec ad2s1210_channels[] = {
+static const struct iio_chan_spec ad2s1210_channels[] = {
{
.type = IIO_ANGL,
.indexed = 1,
TPCI200_CONTROL_D_REG
};
-/* Linked list to save the registered devices */
-static LIST_HEAD(tpci200_list);
-
static int tpci200_slot_unregister(struct ipack_device *dev);
static struct tpci200_board *check_slot(struct ipack_device *dev)
{
struct tpci200_board *tpci200;
- int found = 0;
if (dev == NULL)
return NULL;
- list_for_each_entry(tpci200, &tpci200_list, list) {
- if (tpci200->number == dev->bus_nr) {
- found = 1;
- break;
- }
- }
- if (!found) {
- dev_err(&dev->dev, "Carrier not found\n");
+ tpci200 = dev_get_drvdata(dev->bus->parent);
+
+ if (tpci200 == NULL) {
+ dev_info(&dev->dev, "carrier board not found\n");
return NULL;
}
/* Map internal tpci200 driver user space */
tpci200->info->interface_regs =
- ioremap(pci_resource_start(tpci200->info->pdev,
+ ioremap_nocache(pci_resource_start(tpci200->info->pdev,
TPCI200_IP_INTERFACE_BAR),
TPCI200_IFACE_SIZE);
tpci200->info->ioidint_space =
- ioremap(pci_resource_start(tpci200->info->pdev,
+ ioremap_nocache(pci_resource_start(tpci200->info->pdev,
TPCI200_IO_ID_INT_SPACES_BAR),
TPCI200_IOIDINT_SIZE);
tpci200->info->mem8_space =
- ioremap(pci_resource_start(tpci200->info->pdev,
+ ioremap_nocache(pci_resource_start(tpci200->info->pdev,
TPCI200_MEM8_SPACE_BAR),
TPCI200_MEM8_SIZE);
if (mutex_lock_interruptible(&tpci200->mutex))
return -ERESTARTSYS;
- ipack_device_unregister(dev);
tpci200->slots[dev->slot].dev = NULL;
+ ipack_device_unregister(dev);
mutex_unlock(&tpci200->mutex);
return 0;
virt_addr_space->size = size_to_map;
virt_addr_space->address =
- ioremap((unsigned long)phys_address, size_to_map);
+ ioremap_nocache((unsigned long)phys_address, size_to_map);
out_unlock:
mutex_unlock(&tpci200->mutex);
/* save the bus number given by ipack to logging purpose */
tpci200->number = tpci200->info->ipack_bus->bus_nr;
dev_set_drvdata(&pdev->dev, tpci200);
- /* add the registered device in an internal linked list */
- list_add_tail(&tpci200->list, &tpci200_list);
/*
* Give the same IRQ number as the slot number.
static void __tpci200_pci_remove(struct tpci200_board *tpci200)
{
tpci200_uninstall(tpci200);
- list_del(&tpci200->list);
ipack_bus_unregister(tpci200->info->ipack_bus);
kfree(tpci200->info);
kfree(tpci200);
static void __devexit tpci200_pci_remove(struct pci_dev *dev)
{
- struct tpci200_board *tpci200, *next;
+ struct tpci200_board *tpci200 = pci_get_drvdata(dev);
- /* Search the registered device to uninstall it */
- list_for_each_entry_safe(tpci200, next, &tpci200_list, list) {
- if (tpci200->info->pdev == dev) {
- __tpci200_pci_remove(tpci200);
- break;
- }
- }
+ __tpci200_pci_remove(tpci200);
}
static DEFINE_PCI_DEVICE_TABLE(tpci200_idtable) = {
static void __exit tpci200_drvr_exit_module(void)
{
- struct tpci200_board *tpci200, *next;
-
- list_for_each_entry_safe(tpci200, next, &tpci200_list, list)
- __tpci200_pci_remove(tpci200);
-
pci_unregister_driver(&tpci200_pci_drv);
}
const char *buf, size_t count)
{
struct snd_line6_pcm *line6pcm = dev2pcm(dev);
- int value = simple_strtoul(buf, NULL, 10);
+ int value;
+ int rv;
+
+ rv = kstrtoint(buf, 10, &value);
+ if (rv < 0)
+ return rv;
+
line6pcm->impulse_volume = value;
if (value > 0)
{
struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
- unsigned long value;
+ u8 value;
int ret;
- ret = strict_strtoul(buf, 10, &value);
+ ret = kstrtou8(buf, 10, &value);
if (ret)
return ret;
{
struct usb_line6_variax *variax =
usb_get_intfdata(to_usb_interface(dev));
- unsigned long value;
+ u8 value;
int ret;
- ret = strict_strtoul(buf, 10, &value);
+ ret = kstrtou8(buf, 10, &value);
if (ret)
return ret;
static int parse_msg(struct nvec_chip *nvec, struct nvec_msg *msg)
{
if ((msg->data[0] & 1 << 7) == 0 && msg->data[3]) {
- dev_err(nvec->dev, "ec responded %02x %02x %02x %02x\n",
- msg->data[0], msg->data[1], msg->data[2], msg->data[3]);
+ dev_err(nvec->dev, "ec responded %*ph\n", 4, msg->data);
return -EINVAL;
}
nvec->gpio = pdata->gpio;
nvec->i2c_addr = pdata->i2c_addr;
} else if (nvec->dev->of_node) {
- nvec->gpio = of_get_named_gpio(nvec->dev->of_node, "request-gpios", 0);
+ nvec->gpio = of_get_named_gpio(nvec->dev->of_node,
+ "request-gpios", 0);
if (nvec->gpio < 0) {
dev_err(&pdev->dev, "no gpio specified");
return -ENODEV;
}
- if (of_property_read_u32(nvec->dev->of_node, "slave-addr", &nvec->i2c_addr)) {
+ if (of_property_read_u32(nvec->dev->of_node,
+ "slave-addr", &nvec->i2c_addr)) {
dev_err(&pdev->dev, "no i2c address specified");
return -ENODEV;
}
* License as published by the Free Software Foundation.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/fb.h>
ver = dcon_read(dcon, DCON_REG_ID);
if ((ver >> 8) != 0xDC) {
- printk(KERN_ERR "olpc-dcon: DCON ID not 0xDCxx: 0x%04x instead.\n",
- ver);
+ pr_err("DCON ID not 0xDCxx: 0x%04x instead.\n", ver);
rc = -ENXIO;
goto err;
}
if (is_init) {
- printk(KERN_INFO "olpc-dcon: Discovered DCON version %x\n",
- ver & 0xFF);
+ pr_info("Discovered DCON version %x\n", ver & 0xFF);
rc = pdata->init(dcon);
if (rc != 0) {
- printk(KERN_ERR "olpc-dcon: Unable to init.\n");
+ pr_err("Unable to init.\n");
goto err;
}
}
x = 1;
x = olpc_ec_cmd(0x26, (unsigned char *)&x, 1, NULL, 0);
if (x) {
- printk(KERN_WARNING "olpc-dcon: unable to force dcon to power up: %d!\n",
- x);
+ pr_warn("unable to force dcon to power up: %d!\n", x);
return x;
}
msleep(10); /* we'll be conservative */
x = dcon_read(dcon, DCON_REG_ID);
}
if (x < 0) {
- printk(KERN_ERR "olpc-dcon: unable to stabilize dcon's smbus, reasserting power and praying.\n");
+ pr_err("unable to stabilize dcon's smbus, reasserting power and praying.\n");
BUG_ON(olpc_board_at_least(olpc_board(0xc2)));
x = 0;
olpc_ec_cmd(0x26, (unsigned char *)&x, 1, NULL, 0);
x = 0;
x = olpc_ec_cmd(0x26, (unsigned char *)&x, 1, NULL, 0);
if (x)
- printk(KERN_WARNING "olpc-dcon: unable to force dcon to power down: %d!\n",
- x);
+ pr_warn("unable to force dcon to power down: %d!\n", x);
else
dcon->asleep = sleep;
} else {
dcon->disp_mode |= MODE_BL_ENABLE;
x = dcon_bus_stabilize(dcon, 1);
if (x)
- printk(KERN_WARNING "olpc-dcon: unable to reinit dcon hardware: %d!\n",
- x);
+ pr_warn("unable to reinit dcon hardware: %d!\n", x);
else
dcon->asleep = sleep;
switch (source) {
case DCON_SOURCE_CPU:
- printk(KERN_INFO "dcon_source_switch to CPU\n");
+ pr_info("dcon_source_switch to CPU\n");
/* Enable the scanline interrupt bit */
if (dcon_write(dcon, DCON_REG_MODE,
dcon->disp_mode | MODE_SCAN_INT))
- printk(KERN_ERR
- "olpc-dcon: couldn't enable scanline interrupt!\n");
+ pr_err("couldn't enable scanline interrupt!\n");
else {
/* Wait up to one second for the scanline interrupt */
wait_event_timeout(dcon_wait_queue,
}
if (!dcon->switched)
- printk(KERN_ERR "olpc-dcon: Timeout entering CPU mode; expect a screen glitch.\n");
+ pr_err("Timeout entering CPU mode; expect a screen glitch.\n");
/* Turn off the scanline interrupt */
if (dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode))
- printk(KERN_ERR "olpc-dcon: couldn't disable scanline interrupt!\n");
+ pr_err("couldn't disable scanline interrupt!\n");
/*
* Ideally we'd like to disable interrupts here so that the
* For now, we just hope..
*/
if (!dcon_blank_fb(dcon, false)) {
- printk(KERN_ERR "olpc-dcon: Failed to enter CPU mode\n");
+ pr_err("Failed to enter CPU mode\n");
dcon->pending_src = DCON_SOURCE_DCON;
return;
}
pdata->set_dconload(1);
getnstimeofday(&dcon->load_time);
- printk(KERN_INFO "olpc-dcon: The CPU has control\n");
+ pr_info("The CPU has control\n");
break;
case DCON_SOURCE_DCON:
{
int t;
struct timespec delta_t;
- printk(KERN_INFO "dcon_source_switch to DCON\n");
+ pr_info("dcon_source_switch to DCON\n");
add_wait_queue(&dcon_wait_queue, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
set_current_state(TASK_RUNNING);
if (!dcon->switched) {
- printk(KERN_ERR "olpc-dcon: Timeout entering DCON mode; expect a screen glitch.\n");
+ pr_err("Timeout entering DCON mode; expect a screen glitch.\n");
} else {
/* sometimes the DCON doesn't follow its own rules,
* and doesn't wait for two vsync pulses before
delta_t = timespec_sub(dcon->irq_time, dcon->load_time);
if (dcon->switched && delta_t.tv_sec == 0 &&
delta_t.tv_nsec < NSEC_PER_MSEC * 20) {
- printk(KERN_ERR "olpc-dcon: missed loading, retrying\n");
+ pr_err("missed loading, retrying\n");
pdata->set_dconload(1);
mdelay(41);
pdata->set_dconload(0);
}
dcon_blank_fb(dcon, true);
- printk(KERN_INFO "olpc-dcon: The DCON has control\n");
+ pr_info("The DCON has control\n");
break;
}
default:
if (ret)
return ret;
- printk(KERN_INFO "dcon_freeze_store: %lu\n", output);
+ pr_info("dcon_freeze_store: %lu\n", output);
switch (output) {
case 0:
dcon_device = platform_device_alloc("dcon", -1);
if (dcon_device == NULL) {
- printk(KERN_ERR "dcon: Unable to create the DCON device\n");
+ pr_err("Unable to create the DCON device\n");
rc = -ENOMEM;
goto eirq;
}
platform_set_drvdata(dcon_device, dcon);
if (rc) {
- printk(KERN_ERR "dcon: Unable to add the DCON device\n");
+ pr_err("Unable to add the DCON device\n");
goto edev;
}
switch (status & 3) {
case 3:
- printk(KERN_DEBUG "olpc-dcon: DCONLOAD_MISSED interrupt\n");
+ pr_debug("DCONLOAD_MISSED interrupt\n");
break;
case 2: /* switch to DCON mode */
dcon->switched = true;
getnstimeofday(&dcon->irq_time);
wake_up(&dcon_wait_queue);
- printk(KERN_DEBUG "olpc-dcon: switching w/ status 0/0\n");
+ pr_debug("switching w/ status 0/0\n");
} else {
- printk(KERN_DEBUG "olpc-dcon: scanline interrupt w/CPU\n");
+ pr_debug("scanline interrupt w/CPU\n");
}
}
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/cs5535.h>
#include <linux/gpio.h>
#include <linux/delay.h>
unsigned char lob;
if (gpio_request(OLPC_GPIO_DCON_STAT0, "OLPC-DCON")) {
- printk(KERN_ERR "olpc-dcon: failed to request STAT0 GPIO\n");
+ pr_err("failed to request STAT0 GPIO\n");
return -EIO;
}
if (gpio_request(OLPC_GPIO_DCON_STAT1, "OLPC-DCON")) {
- printk(KERN_ERR "olpc-dcon: failed to request STAT1 GPIO\n");
+ pr_err("failed to request STAT1 GPIO\n");
goto err_gp_stat1;
}
if (gpio_request(OLPC_GPIO_DCON_IRQ, "OLPC-DCON")) {
- printk(KERN_ERR "olpc-dcon: failed to request IRQ GPIO\n");
+ pr_err("failed to request IRQ GPIO\n");
goto err_gp_irq;
}
if (gpio_request(OLPC_GPIO_DCON_LOAD, "OLPC-DCON")) {
- printk(KERN_ERR "olpc-dcon: failed to request LOAD GPIO\n");
+ pr_err("failed to request LOAD GPIO\n");
goto err_gp_load;
}
if (gpio_request(OLPC_GPIO_DCON_BLANK, "OLPC-DCON")) {
- printk(KERN_ERR "olpc-dcon: failed to request BLANK GPIO\n");
+ pr_err("failed to request BLANK GPIO\n");
goto err_gp_blank;
}
/* Register the interrupt handler */
if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", dcon)) {
- printk(KERN_ERR "olpc-dcon: failed to request DCON's irq\n");
+ pr_err("failed to request DCON's irq\n");
goto err_req_irq;
}
* License as published by the Free Software Foundation.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/pci.h>
pdev = pci_get_device(PCI_VENDOR_ID_VIA,
PCI_DEVICE_ID_VIA_VX855, NULL);
if (!pdev) {
- printk(KERN_ERR "cannot find VX855 PCI ID\n");
+ pr_err("cannot find VX855 PCI ID\n");
return 1;
}
/* we're sharing the IRQ with ACPI */
irq = acpi_gbl_FADT.sci_interrupt;
if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", dcon)) {
- printk(KERN_ERR PREFIX "DCON (IRQ%d) allocation failed\n", irq);
+ pr_err("DCON (IRQ%d) allocation failed\n", irq);
return 1;
}
return 0;
}
+static int omap_crtc_set_property(struct drm_crtc *crtc,
+ struct drm_property *property, uint64_t val)
+{
+ struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+ return omap_plane_set_property(omap_crtc->plane, property, val);
+}
+
static const struct drm_crtc_funcs omap_crtc_funcs = {
.set_config = drm_crtc_helper_set_config,
.destroy = omap_crtc_destroy,
.page_flip = omap_crtc_page_flip_locked,
+ .set_property = omap_crtc_set_property,
};
static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
drm_crtc_init(dev, crtc, &omap_crtc_funcs);
drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);
+ omap_plane_install_properties(omap_crtc->plane, &crtc->base);
+
return crtc;
fail:
return 0;
}
-irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
+static irqreturn_t omap_dmm_irq_handler(int irq, void *arg)
{
struct dmm *dmm = arg;
uint32_t status = readl(dmm->base + DMM_PAT_IRQSTATUS);
int num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
if (!block)
- return 0;
+ return ERR_PTR(-ENOMEM);
block->fmt = TILFMT_PAGE;
* Utils
*/
-/* calculate the tiler space address of a pixel in a view orientation */
-static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y)
+/* calculate the tiler space address of a pixel in a view orientation...
+ * below description copied from the display subsystem section of TRM:
+ *
+ * When the TILER is addressed, the bits:
+ * [28:27] = 0x0 for 8-bit tiled
+ * 0x1 for 16-bit tiled
+ * 0x2 for 32-bit tiled
+ * 0x3 for page mode
+ * [31:29] = 0x0 for 0-degree view
+ * 0x1 for 180-degree view + mirroring
+ * 0x2 for 0-degree view + mirroring
+ * 0x3 for 180-degree view
+ * 0x4 for 270-degree view + mirroring
+ * 0x5 for 270-degree view
+ * 0x6 for 90-degree view
+ * 0x7 for 90-degree view + mirroring
+ * Otherwise the bits indicated the corresponding bit address to access
+ * the SDRAM.
+ */
+static u32 tiler_get_address(enum tiler_fmt fmt, u32 orient, u32 x, u32 y)
{
u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment;
x_mask = MASK(x_bits);
y_mask = MASK(y_bits);
- if (x < 0 || x > x_mask || y < 0 || y > y_mask)
+ if (x < 0 || x > x_mask || y < 0 || y > y_mask) {
+ DBG("invalid coords: %u < 0 || %u > %u || %u < 0 || %u > %u",
+ x, x, x_mask, y, y, y_mask);
return 0;
+ }
/* account for mirroring */
if (orient & MASK_X_INVERT)
{
BUG_ON(!validfmt(block->fmt));
- return TILVIEW_8BIT + tiler_get_address(0, block->fmt,
+ return TILVIEW_8BIT + tiler_get_address(block->fmt, 0,
block->area.p0.x * geom[block->fmt].slot_w,
block->area.p0.y * geom[block->fmt].slot_h);
}
+dma_addr_t tiler_tsptr(struct tiler_block *block, uint32_t orient,
+ uint32_t x, uint32_t y)
+{
+ struct tcm_pt *p = &block->area.p0;
+ BUG_ON(!validfmt(block->fmt));
+
+ return tiler_get_address(block->fmt, orient,
+ (p->x * geom[block->fmt].slot_w) + x,
+ (p->y * geom[block->fmt].slot_h) + y);
+}
+
void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h)
{
BUG_ON(!validfmt(fmt));
*h = round_up(*h, geom[fmt].slot_h);
}
-uint32_t tiler_stride(enum tiler_fmt fmt)
+uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient)
{
BUG_ON(!validfmt(fmt));
- return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft);
+ if (orient & MASK_XY_FLIP)
+ return 1 << (CONT_HEIGHT_BITS + geom[fmt].x_shft);
+ else
+ return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft);
}
size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h)
#define TILER_WIDTH (1 << (CONT_WIDTH_BITS - SLOT_WIDTH_BITS))
#define TILER_HEIGHT (1 << (CONT_HEIGHT_BITS - SLOT_HEIGHT_BITS))
-/* tiler space addressing bitfields */
+/*
+Table 15-11. Coding and Description of TILER Orientations
+S Y X Description Alternate description
+0 0 0 0-degree view Natural view
+0 0 1 0-degree view with vertical mirror 180-degree view with horizontal mirror
+0 1 0 0-degree view with horizontal mirror 180-degree view with vertical mirror
+0 1 1 180-degree view
+1 0 0 90-degree view with vertical mirror 270-degree view with horizontal mirror
+1 0 1 270-degree view
+1 1 0 90-degree view
+1 1 1 90-degree view with horizontal mirror 270-degree view with vertical mirror
+ */
#define MASK_XY_FLIP (1 << 31)
#define MASK_Y_INVERT (1 << 30)
#define MASK_X_INVERT (1 << 29)
/* utilities */
dma_addr_t tiler_ssptr(struct tiler_block *block);
-uint32_t tiler_stride(enum tiler_fmt fmt);
+dma_addr_t tiler_tsptr(struct tiler_block *block, uint32_t orient,
+ uint32_t x, uint32_t y);
+uint32_t tiler_stride(enum tiler_fmt fmt, uint32_t orient);
size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h);
size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h);
void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h);
*/
static void dev_lastclose(struct drm_device *dev)
{
+ int i;
+
/* we don't support vga-switcheroo.. so just make sure the fbdev
* mode is active
*/
DBG("lastclose: dev=%p", dev);
+ /* need to restore default rotation state.. not sure if there is
+ * a cleaner way to restore properties to default state? Maybe
+ * a flag that properties should automatically be restored to
+ * default state on lastclose?
+ */
+ for (i = 0; i < priv->num_crtcs; i++) {
+ drm_object_property_set_value(&priv->crtcs[i]->base,
+ priv->rotation_prop, 0);
+ }
+
+ for (i = 0; i < priv->num_planes; i++) {
+ drm_object_property_set_value(&priv->planes[i]->base,
+ priv->rotation_prop, 0);
+ }
+
ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
if (ret)
DBG("failed to restore crtc mode");
.irq_postinstall = dev_irq_postinstall,
.irq_uninstall = dev_irq_uninstall,
.irq_handler = dev_irq_handler,
- .reclaim_buffers = drm_core_reclaim_buffers,
#ifdef CONFIG_DEBUG_FS
.debugfs_init = omap_debugfs_init,
.debugfs_cleanup = omap_debugfs_cleanup,
struct list_head obj_list;
bool has_dmm;
+
+ /* properties: */
+ struct drm_property *rotation_prop;
+ struct drm_property *zorder_prop;
+};
+
+/* this should probably be in drm-core to standardize amongst drivers */
+#define DRM_ROTATE_0 0
+#define DRM_ROTATE_90 1
+#define DRM_ROTATE_180 2
+#define DRM_ROTATE_270 3
+#define DRM_REFLECT_X 4
+#define DRM_REFLECT_Y 5
+
+/* parameters which describe (unrotated) coordinates of scanout within a fb: */
+struct omap_drm_window {
+ uint32_t rotation;
+ int32_t crtc_x, crtc_y; /* signed because can be offscreen */
+ uint32_t crtc_w, crtc_h;
+ uint32_t src_x, src_y;
+ uint32_t src_w, src_h;
};
#ifdef CONFIG_DEBUG_FS
uint32_t src_w, uint32_t src_h);
void omap_plane_on_endwin(struct drm_plane *plane,
void (*fxn)(void *), void *arg);
+void omap_plane_install_properties(struct drm_plane *plane,
+ struct drm_mode_object *obj);
+int omap_plane_set_property(struct drm_plane *plane,
+ struct drm_property *property, uint64_t val);
struct drm_encoder *omap_encoder_init(struct drm_device *dev,
struct omap_overlay_manager *mgr);
int omap_framebuffer_replace(struct drm_framebuffer *a,
struct drm_framebuffer *b, void *arg,
void (*unpin)(void *arg, struct drm_gem_object *bo));
-void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
- struct omap_overlay_info *info);
+void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
+ struct omap_drm_window *win, struct omap_overlay_info *info);
struct drm_connector *omap_framebuffer_get_next_connector(
struct drm_framebuffer *fb, struct drm_connector *from);
void omap_framebuffer_flush(struct drm_framebuffer *fb,
bool remap);
int omap_gem_put_pages(struct drm_gem_object *obj);
uint32_t omap_gem_flags(struct drm_gem_object *obj);
+int omap_gem_rotated_paddr(struct drm_gem_object *obj, uint32_t orient,
+ int x, int y, dma_addr_t *paddr);
uint64_t omap_gem_mmap_offset(struct drm_gem_object *obj);
size_t omap_gem_mmap_size(struct drm_gem_object *obj);
+int omap_gem_tiled_size(struct drm_gem_object *obj, uint16_t *w, uint16_t *h);
+int omap_gem_tiled_stride(struct drm_gem_object *obj, uint32_t orient);
struct dma_buf * omap_gem_prime_export(struct drm_device *dev,
struct drm_gem_object *obj, int flags);
*/
#include "omap_drv.h"
+#include "omap_dmm_tiler.h"
#include "drm_crtc.h"
#include "drm_crtc_helper.h"
.dirty = omap_framebuffer_dirty,
};
+static uint32_t get_linear_addr(struct plane *plane,
+ const struct format *format, int n, int x, int y)
+{
+ uint32_t offset;
+
+ offset = plane->offset +
+ (x * format->planes[n].stride_bpp) +
+ (y * plane->pitch / format->planes[n].sub_y);
+
+ return plane->paddr + offset;
+}
+
/* update ovl info for scanout, handles cases of multi-planar fb's, etc.
*/
-void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, int x, int y,
- struct omap_overlay_info *info)
+void omap_framebuffer_update_scanout(struct drm_framebuffer *fb,
+ struct omap_drm_window *win, struct omap_overlay_info *info)
{
struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb);
const struct format *format = omap_fb->format;
struct plane *plane = &omap_fb->planes[0];
- unsigned int offset;
+ uint32_t x, y, orient = 0;
+
+ info->color_mode = format->dss_format;
+
+ info->pos_x = win->crtc_x;
+ info->pos_y = win->crtc_y;
+ info->out_width = win->crtc_w;
+ info->out_height = win->crtc_h;
+ info->width = win->src_w;
+ info->height = win->src_h;
+
+ x = win->src_x;
+ y = win->src_y;
+
+ if (omap_gem_flags(plane->bo) & OMAP_BO_TILED) {
+ uint32_t w = win->src_w;
+ uint32_t h = win->src_h;
+
+ switch (win->rotation & 0xf) {
+ default:
+ dev_err(fb->dev->dev, "invalid rotation: %02x",
+ (uint32_t)win->rotation);
+ /* fallthru to default to no rotation */
+ case 0:
+ case BIT(DRM_ROTATE_0):
+ orient = 0;
+ break;
+ case BIT(DRM_ROTATE_90):
+ orient = MASK_XY_FLIP | MASK_X_INVERT;
+ break;
+ case BIT(DRM_ROTATE_180):
+ orient = MASK_X_INVERT | MASK_Y_INVERT;
+ break;
+ case BIT(DRM_ROTATE_270):
+ orient = MASK_XY_FLIP | MASK_Y_INVERT;
+ break;
+ }
- offset = plane->offset +
- (x * format->planes[0].stride_bpp) +
- (y * plane->pitch / format->planes[0].sub_y);
+ if (win->rotation & BIT(DRM_REFLECT_X))
+ orient ^= MASK_X_INVERT;
+
+ if (win->rotation & BIT(DRM_REFLECT_Y))
+ orient ^= MASK_Y_INVERT;
+
+ /* adjust x,y offset for flip/invert: */
+ if (orient & MASK_XY_FLIP)
+ swap(w, h);
+ if (orient & MASK_Y_INVERT)
+ y += h - 1;
+ if (orient & MASK_X_INVERT)
+ x += w - 1;
- info->color_mode = format->dss_format;
- info->paddr = plane->paddr + offset;
- info->screen_width = plane->pitch / format->planes[0].stride_bpp;
+ omap_gem_rotated_paddr(plane->bo, orient, x, y, &info->paddr);
+ info->rotation_type = OMAP_DSS_ROT_TILER;
+ info->screen_width = omap_gem_tiled_stride(plane->bo, orient);
+ } else {
+ info->paddr = get_linear_addr(plane, format, 0, x, y);
+ info->rotation_type = OMAP_DSS_ROT_DMA;
+ info->screen_width = plane->pitch;
+ }
+
+ /* convert to pixels: */
+ info->screen_width /= format->planes[0].stride_bpp;
if (format->dss_format == OMAP_DSS_COLOR_NV12) {
plane = &omap_fb->planes[1];
- offset = plane->offset +
- (x * format->planes[1].stride_bpp) +
- (y * plane->pitch / format->planes[1].sub_y);
- info->p_uv_addr = plane->paddr + offset;
+
+ if (info->rotation_type == OMAP_DSS_ROT_TILER) {
+ WARN_ON(!(omap_gem_flags(plane->bo) & OMAP_BO_TILED));
+ omap_gem_rotated_paddr(plane->bo, orient,
+ x/2, y/2, &info->p_uv_addr);
+ } else {
+ info->p_uv_addr = get_linear_addr(plane, format, 1, x, y);
+ }
} else {
info->p_uv_addr = 0;
}
size = pitch * mode_cmd->height / format->planes[i].sub_y;
- if (size > (bos[i]->size - mode_cmd->offsets[i])) {
+ if (size > (omap_gem_mmap_size(bos[i]) - mode_cmd->offsets[i])) {
dev_err(dev->dev, "provided buffer object is too small! %d < %d\n",
bos[i]->size - mode_cmd->offsets[i], size);
ret = -EINVAL;
return size;
}
+/* get tiled size, returns -EINVAL if not tiled buffer */
+int omap_gem_tiled_size(struct drm_gem_object *obj, uint16_t *w, uint16_t *h)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ if (omap_obj->flags & OMAP_BO_TILED) {
+ *w = omap_obj->width;
+ *h = omap_obj->height;
+ return 0;
+ }
+ return -EINVAL;
+}
/* Normal handling for the case of faulting in non-tiled buffers */
static int fault_1d(struct drm_gem_object *obj,
return ret;
}
+/* Get rotated scanout address (only valid if already pinned), at the
+ * specified orientation and x,y offset from top-left corner of buffer
+ * (only valid for tiled 2d buffers)
+ */
+int omap_gem_rotated_paddr(struct drm_gem_object *obj, uint32_t orient,
+ int x, int y, dma_addr_t *paddr)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ int ret = -EINVAL;
+
+ mutex_lock(&obj->dev->struct_mutex);
+ if ((omap_obj->paddr_cnt > 0) && omap_obj->block &&
+ (omap_obj->flags & OMAP_BO_TILED)) {
+ *paddr = tiler_tsptr(omap_obj->block, orient, x, y);
+ ret = 0;
+ }
+ mutex_unlock(&obj->dev->struct_mutex);
+ return ret;
+}
+
+/* Get tiler stride for the buffer (only valid for 2d tiled buffers) */
+int omap_gem_tiled_stride(struct drm_gem_object *obj, uint32_t orient)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ int ret = -EINVAL;
+ if (omap_obj->flags & OMAP_BO_TILED)
+ ret = tiler_stride(gem2fmt(omap_obj->flags), orient);
+ return ret;
+}
+
/* acquire pages when needed (for example, for DMA where physically
* contiguous buffer is not required
*/
*/
usergart[i].height = h;
usergart[i].height_shift = ilog2(h);
- usergart[i].stride_pfn = tiler_stride(fmts[i]) >> PAGE_SHIFT;
+ usergart[i].stride_pfn = tiler_stride(fmts[i], 0) >> PAGE_SHIFT;
usergart[i].slot_shift = ilog2((PAGE_SIZE / h) >> i);
for (j = 0; j < NUM_USERGART_ENTRIES; j++) {
struct usergart_entry *entry = &usergart[i].entry[j];
#include <linux/kfifo.h>
#include "omap_drv.h"
+#include "omap_dmm_tiler.h"
/* some hackery because omapdss has an 'enum omap_plane' (which would be
* better named omap_plane_id).. and compiler seems unhappy about having
struct omap_overlay *ovl;
struct omap_overlay_info info;
- /* Source values, converted to integers because we don't support
- * fractional positions:
- */
- unsigned int src_x, src_y;
+ /* position/orientation of scanout within the fb: */
+ struct omap_drm_window win;
+
/* last fb that we pinned: */
struct drm_framebuffer *pinned_fb;
{
struct omap_plane *omap_plane = to_omap_plane(plane);
struct omap_overlay_info *info = &omap_plane->info;
+ struct omap_drm_window *win = &omap_plane->win;
int ret;
ret = update_pin(plane, plane->fb);
return;
}
- omap_framebuffer_update_scanout(plane->fb,
- omap_plane->src_x, omap_plane->src_y, info);
+ omap_framebuffer_update_scanout(plane->fb, win, info);
DBG("%s: %d,%d: %08x %08x (%d)", omap_plane->ovl->name,
- omap_plane->src_x, omap_plane->src_y,
+ win->src_x, win->src_y,
(u32)info->paddr, (u32)info->p_uv_addr,
info->screen_width);
}
uint32_t src_w, uint32_t src_h)
{
struct omap_plane *omap_plane = to_omap_plane(plane);
+ struct omap_drm_window *win = &omap_plane->win;
+
+ win->crtc_x = crtc_x;
+ win->crtc_y = crtc_y;
+ win->crtc_w = crtc_w;
+ win->crtc_h = crtc_h;
/* src values are in Q16 fixed point, convert to integer: */
- src_x = src_x >> 16;
- src_y = src_y >> 16;
- src_w = src_w >> 16;
- src_h = src_h >> 16;
-
- omap_plane->info.pos_x = crtc_x;
- omap_plane->info.pos_y = crtc_y;
- omap_plane->info.out_width = crtc_w;
- omap_plane->info.out_height = crtc_h;
- omap_plane->info.width = src_w;
- omap_plane->info.height = src_h;
- omap_plane->src_x = src_x;
- omap_plane->src_y = src_y;
+ win->src_x = src_x >> 16;
+ win->src_y = src_y >> 16;
+ win->src_w = src_w >> 16;
+ win->src_h = src_h >> 16;
/* note: this is done after this fxn returns.. but if we need
* to do a commit/update_scanout, etc before this returns we
static int omap_plane_disable(struct drm_plane *plane)
{
+ struct omap_plane *omap_plane = to_omap_plane(plane);
+ omap_plane->win.rotation = BIT(DRM_ROTATE_0);
return omap_plane_dpms(plane, DRM_MODE_DPMS_OFF);
}
install_irq(plane);
}
+/* helper to install properties which are common to planes and crtcs */
+void omap_plane_install_properties(struct drm_plane *plane,
+ struct drm_mode_object *obj)
+{
+ struct drm_device *dev = plane->dev;
+ struct omap_drm_private *priv = dev->dev_private;
+ struct drm_property *prop;
+
+ prop = priv->rotation_prop;
+ if (!prop) {
+ const struct drm_prop_enum_list props[] = {
+ { DRM_ROTATE_0, "rotate-0" },
+ { DRM_ROTATE_90, "rotate-90" },
+ { DRM_ROTATE_180, "rotate-180" },
+ { DRM_ROTATE_270, "rotate-270" },
+ { DRM_REFLECT_X, "reflect-x" },
+ { DRM_REFLECT_Y, "reflect-y" },
+ };
+ prop = drm_property_create_bitmask(dev, 0, "rotation",
+ props, ARRAY_SIZE(props));
+ if (prop == NULL)
+ return;
+ priv->rotation_prop = prop;
+ }
+ drm_object_attach_property(obj, prop, 0);
+
+ prop = priv->zorder_prop;
+ if (!prop) {
+ prop = drm_property_create_range(dev, 0, "zorder", 0, 3);
+ if (prop == NULL)
+ return;
+ priv->zorder_prop = prop;
+ }
+ drm_object_attach_property(obj, prop, 0);
+}
+
+int omap_plane_set_property(struct drm_plane *plane,
+ struct drm_property *property, uint64_t val)
+{
+ struct omap_plane *omap_plane = to_omap_plane(plane);
+ struct omap_drm_private *priv = plane->dev->dev_private;
+ int ret = -EINVAL;
+
+ if (property == priv->rotation_prop) {
+ struct omap_overlay *ovl = omap_plane->ovl;
+
+ DBG("%s: rotation: %02x", ovl->name, (uint32_t)val);
+ omap_plane->win.rotation = val;
+
+ if (ovl->is_enabled(ovl))
+ ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
+ else
+ ret = 0;
+ } else if (property == priv->zorder_prop) {
+ struct omap_overlay *ovl = omap_plane->ovl;
+
+ DBG("%s: zorder: %d", ovl->name, (uint32_t)val);
+ omap_plane->info.zorder = val;
+
+ if (ovl->is_enabled(ovl))
+ ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
+ else
+ ret = 0;
+ }
+
+ return ret;
+}
+
static const struct drm_plane_funcs omap_plane_funcs = {
.update_plane = omap_plane_update,
.disable_plane = omap_plane_disable,
.destroy = omap_plane_destroy,
+ .set_property = omap_plane_set_property,
};
/* initialize plane */
drm_plane_init(dev, plane, possible_crtcs, &omap_plane_funcs,
omap_plane->formats, omap_plane->nformats, priv);
+ omap_plane_install_properties(plane, &plane->base);
+
/* get our starting configuration, set defaults for parameters
* we don't currently use, etc:
*/
omap_plane->info.rotation = OMAP_DSS_ROT_0;
omap_plane->info.global_alpha = 0xff;
omap_plane->info.mirror = 0;
- omap_plane->info.mirror = 0;
/* Set defaults depending on whether we are a CRTC or overlay
* layer.
oz_trace("Freeing endpoint memory\n");
kfree(ep);
}
+/*------------------------------------------------------------------------------
+ * Context: softirq
+ */
+void oz_complete_buffered_urb(struct oz_port *port, struct oz_endpoint *ep,
+ struct urb *urb)
+{
+ u8 data_len, available_space, copy_len;
+
+ memcpy(&data_len, &ep->buffer[ep->out_ix], sizeof(u8));
+ if (data_len <= urb->transfer_buffer_length)
+ available_space = data_len;
+ else
+ available_space = urb->transfer_buffer_length;
+
+ if (++ep->out_ix == ep->buffer_size)
+ ep->out_ix = 0;
+ copy_len = ep->buffer_size - ep->out_ix;
+ if (copy_len >= available_space)
+ copy_len = available_space;
+ memcpy(urb->transfer_buffer, &ep->buffer[ep->out_ix], copy_len);
+
+ if (copy_len < available_space) {
+ memcpy((urb->transfer_buffer + copy_len), ep->buffer,
+ (available_space - copy_len));
+ ep->out_ix = available_space - copy_len;
+ } else {
+ ep->out_ix += copy_len;
+ }
+ urb->actual_length = available_space;
+ if (ep->out_ix == ep->buffer_size)
+ ep->out_ix = 0;
+
+ ep->buffered_units--;
+ oz_trace("Trying to give back buffered frame of size=%d\n",
+ available_space);
+ oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
+}
+
/*------------------------------------------------------------------------------
* Context: softirq
*/
ep = port->in_ep[ep_addr];
else
ep = port->out_ep[ep_addr];
+
+ /*For interrupt endpoint check for buffered data
+ * & complete urb
+ */
+ if (((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+ && ep->buffered_units > 0) {
+ oz_free_urb_link(urbl);
+ spin_unlock_bh(&port->ozhcd->hcd_lock);
+ oz_complete_buffered_urb(port, ep, urb);
+ return 0;
+ }
+
if (ep && port->hpd) {
list_add_tail(&urbl->link, &ep->urb_list);
if (!in_dir && ep_addr && (ep->credit < 0)) {
} else {
int copy_len;
oz_trace("VENDOR-CLASS - cnf\n");
- if (data_len <= urb->transfer_buffer_length)
- copy_len = data_len;
- else
- copy_len = urb->transfer_buffer_length;
- if (copy_len)
+ if (data_len) {
+ if (data_len <= urb->transfer_buffer_length)
+ copy_len = data_len;
+ else
+ copy_len = urb->transfer_buffer_length;
memcpy(urb->transfer_buffer, data, copy_len);
- urb->actual_length = copy_len;
+ urb->actual_length = copy_len;
+ }
oz_complete_urb(hcd, urb, 0, 0);
}
}
urb->actual_length = copy_len;
oz_complete_urb(port->ozhcd->hcd, urb, 0, 0);
return;
+ } else {
+ oz_trace("buffering frame as URB is not available\n");
+ oz_hcd_buffer_data(ep, data, data_len);
}
break;
case USB_ENDPOINT_XFER_ISOC:
ep = ep_from_link(e);
if (ep->credit < 0)
continue;
- ep->credit += (now - ep->last_jiffies);
+ ep->credit += jiffies_to_msecs(now - ep->last_jiffies);
if (ep->credit > ep->credit_ceiling)
ep->credit = ep->credit_ceiling;
oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num, 0, 0, ep->credit);
urbl = list_first_entry(&ep->urb_list,
struct oz_urb_link, link);
urb = urbl->urb;
- if (ep->credit < urb->number_of_packets)
+ if ((ep->credit + 1) < urb->number_of_packets)
break;
ep->credit -= urb->number_of_packets;
oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num, 0, 0,
}
continue;
}
- ep->credit += (now - ep->last_jiffies);
+ ep->credit += jiffies_to_msecs(now - ep->last_jiffies);
oz_event_log(OZ_EVT_EP_CREDIT, ep->ep_num | USB_DIR_IN,
0, 0, ep->credit);
ep->last_jiffies = now;
int len = 0;
int copy_len;
int i;
- if (ep->credit < urb->number_of_packets)
+ if ((ep->credit + 1) < urb->number_of_packets)
break;
if (ep->buffered_units < urb->number_of_packets)
break;
int buffer_size = 0;
oz_trace("%d bEndpointAddress = %x\n", i, ep_addr);
- if ((ep_addr & USB_ENDPOINT_DIR_MASK) &&
- ((hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_ISOC)) {
- buffer_size = 24*1024;
+ if (ep_addr & USB_ENDPOINT_DIR_MASK) {
+ switch (hep->desc.bmAttributes &
+ USB_ENDPOINT_XFERTYPE_MASK) {
+ case USB_ENDPOINT_XFER_ISOC:
+ buffer_size = 24*1024;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ buffer_size = 128;
+ break;
+ }
}
ep = oz_ep_alloc(mem_flags, buffer_size);
int data_len = 0;
if ((setup->bRequestType & USB_DIR_IN) == 0)
data_len = wlength;
+ urb->actual_length = data_len;
if (oz_usb_control_req(port->hpd, req_id, setup,
urb->transfer_buffer, data_len)) {
rc = -ENOMEM;
MODULE_AUTHOR("Chris Kelly");
MODULE_DESCRIPTION("Ozmo Devices USB over WiFi hcd driver");
-MODULE_VERSION("1.0.10");
+MODULE_VERSION("1.0.13");
MODULE_LICENSE("GPL");
/*------------------------------------------------------------------------------
*/
#define OZ_MAX_TX_POOL_SIZE 6
-/* Maximum number of uncompleted isoc frames that can be pending in network.
- */
-#define OZ_MAX_SUBMITTED_ISOC 16
-/* Maximum number of uncompleted isoc frames that can be pending in Tx Queue.
- */
-#define OZ_MAX_TX_QUEUE_ISOC 32
/*------------------------------------------------------------------------------
*/
static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd);
if (!(pd->mode & OZ_F_ISOC_ANYTIME)) {
struct oz_tx_frame *isoc_unit = NULL;
int nb = pd->nb_queued_isoc_frames;
- if (nb >= OZ_MAX_TX_QUEUE_ISOC) {
+ if (nb >= pd->isoc_latency) {
oz_trace2(OZ_TRACE_TX_FRAMES,
"Dropping ISOC Unit nb= %d\n",
nb);
u8 heartbeat_requested;
u8 mode;
u8 ms_per_isoc;
+ unsigned isoc_latency;
unsigned max_stream_buffering;
int nb_queued_frames;
int nb_queued_isoc_frames;
pd->ms_per_isoc = body->ms_per_isoc;
if (!pd->ms_per_isoc)
pd->ms_per_isoc = 4;
+
+ switch (body->ms_isoc_latency & OZ_LATENCY_MASK) {
+ case OZ_ONE_MS_LATENCY:
+ pd->isoc_latency = (body->ms_isoc_latency &
+ ~OZ_LATENCY_MASK) / pd->ms_per_isoc;
+ break;
+ case OZ_TEN_MS_LATENCY:
+ pd->isoc_latency = ((body->ms_isoc_latency &
+ ~OZ_LATENCY_MASK) * 10) / pd->ms_per_isoc;
+ break;
+ default:
+ pd->isoc_latency = OZ_MAX_TX_QUEUE_ISOC;
+ }
}
if (body->max_len_div16)
pd->max_tx_size = ((u16)body->max_len_div16)<<4;
/* Converts millisecs to jiffies.
*/
-#define oz_ms_to_jiffies(__x) (((__x)*1000)/HZ)
+#define oz_ms_to_jiffies(__x) msecs_to_jiffies(__x)
/* Quantum milliseconds.
*/
/* Maximun sizes of tx frames. */
#define OZ_MAX_TX_SIZE 1514
+/* Maximum number of uncompleted isoc frames that can be pending in network. */
+#define OZ_MAX_SUBMITTED_ISOC 16
+
+/* Maximum number of uncompleted isoc frames that can be pending in Tx Queue. */
+#define OZ_MAX_TX_QUEUE_ISOC 32
+
/* Application handler functions.
*/
typedef int (*oz_app_init_fn_t)(void);
#define OZ_LAST_PN_HALF_CYCLE 127
+#define OZ_LATENCY_MASK 0xc0
+#define OZ_ONE_MS_LATENCY 0x40
+#define OZ_TEN_MS_LATENCY 0x80
+
/* Connect request data structure.
*/
struct oz_elt_connect_req {
u8 pd_info;
u8 session_id;
u8 presleep;
- u8 resv2;
+ u8 ms_isoc_latency;
u8 host_vendor;
u8 keep_alive;
u16 apps;
#define r_ctr(x) (parport_read_control((x)->port))
#define r_dtr(x) (parport_read_data((x)->port))
#define r_str(x) (parport_read_status((x)->port))
-#define w_ctr(x, y) do { parport_write_control((x)->port, (y)); } while (0)
-#define w_dtr(x, y) do { parport_write_data((x)->port, (y)); } while (0)
+#define w_ctr(x, y) (parport_write_control((x)->port, (y)))
+#define w_dtr(x, y) (parport_write_data((x)->port, (y)))
/* this defines which bits are to be used and which ones to be ignored */
/* logical or of the output bits involved in the scan matrix */
int (*reset_port)(struct net_device *dev);
- /* Softmac-generated frames (mamagement) are TXed via this
+ /* Softmac-generated frames (management) are TXed via this
* callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is
* not set. As some cards may have different HW queues that
* one might want to use for data and management frames
u8 u1bAIFS;
u32 u4bAcParam;
pAcParam = (PAC_PARAM)(&AcParam);
- /* Retrieve paramters to update. */
+ /* Retrieve parameters to update. */
u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G) ? 9 : 20) + aSifsTime;
u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit))<<AC_PARAM_TXOP_LIMIT_OFFSET)|
(((u32)(pAcParam->f.Ecw.f.ECWmax))<<AC_PARAM_ECW_MAX_OFFSET)|
u8 u1bAIFS;
u32 u4bAcParam;
- /* Retrieve paramters to update. */
+ /* Retrieve parameters to update. */
eACI = pAcParam->f.AciAifsn.f.ACI;
/* Mode G/A: slotTimeTimer = 9; Mode B: 20 */
u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * (((mode&IEEE_G) == IEEE_G) ? 9 : 20) + aSifsTime;
/* by amy for power save */
/* by amy for antenna */
#define EEPROM_SW_REVD_OFFSET 0x3f
-/* BIT[8-9] is for SW Antenna Diversity. Only the value EEPROM_SW_AD_ENABLE means enable, other values are diable. */
+
+/* BIT[8-9] is for SW Antenna Diversity.
+ * Only the value EEPROM_SW_AD_ENABLE means enable, other values are disable.
+ */
#define EEPROM_SW_AD_MASK 0x0300
#define EEPROM_SW_AD_ENABLE 0x0100
-/* BIT[10-11] determine if Antenna 1 is the Default Antenna. Only the value EEPROM_DEF_ANT_1 means TRUE, other values are FALSE. */
+/* BIT[10-11] determine if Antenna 1 is the Default Antenna.
+ * Only the value EEPROM_DEF_ANT_1 means TRUE, other values are FALSE.
+ */
#define EEPROM_DEF_ANT_MASK 0x0C00
#define EEPROM_DEF_ANT_1 0x0400
/*by amy for antenna */
u8 u1bAIFS;
u32 u4bAcParam;
- /* Retrieve paramters to update. */
+ /* Retrieve parameters to update. */
eACI = pAcParam->f.AciAifsn.f.ACI;
u1bAIFS = pAcParam->f.AciAifsn.f.AIFSN * ChnlAccessSetting->SlotTimeTimer + aSifsTime;
u4bAcParam = ((((u32)(pAcParam->f.TXOPLimit)) << AC_PARAM_TXOP_LIMIT_OFFSET) |
case FW_SOURCE_IMG_FILE:
{
if (pfirmware->firmware_buf_size[init_step] == 0) {
- const char *fw_name[3] = { "RTL8192E/boot.img",
- "RTL8192E/main.img",
- "RTL8192E/data.img"
- };
+ const char *fw_name[3] = {
+ RTL8192E_BOOT_IMG_FW,
+ RTL8192E_MAIN_IMG_FW,
+ RTL8192E_DATA_IMG_FW
+ };
const struct firmware *fw_entry;
int rc;
rc = request_firmware(&fw_entry,
#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4*(v/4) - 8)
+#define RTL8192E_BOOT_IMG_FW "RTL8192E/boot.img"
+#define RTL8192E_MAIN_IMG_FW "RTL8192E/main.img"
+#define RTL8192E_DATA_IMG_FW "RTL8192E/data.img"
+
enum firmware_init_step {
FW_INIT_STEP0_BOOT = 0,
FW_INIT_STEP1_MAIN = 1,
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(RTL8192E_BOOT_IMG_FW);
+MODULE_FIRMWARE(RTL8192E_MAIN_IMG_FW);
+MODULE_FIRMWARE(RTL8192E_DATA_IMG_FW);
module_param(ifname, charp, S_IRUGO|S_IWUSR);
module_param(hwwep, int, S_IRUGO|S_IWUSR);
if (priv->ResetProgress == RESET_TYPE_SILENT) {
RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF),
- "GPIOChangeRFWorkItemCallBack(): Silent Reseting!!!!!!!\n");
+ "GPIOChangeRFWorkItemCallBack(): Silent Reset!!!!!!!\n");
return;
}
struct rtllib_network *network, u16 type);
int (*is_qos_active)(struct net_device *dev, struct sk_buff *skb);
- /* Softmac-generated frames (mamagement) are TXed via this
+ /* Softmac-generated frames (management) are TXed via this
* callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is
* not set. As some cards may have different HW queues that
* one might want to use for data and management frames
* the option to have two callbacks might be useful.
- * This fucntion can't sleep.
+ * This function can't sleep.
*/
int (*softmac_hard_start_xmit)(struct sk_buff *skb,
struct net_device *dev);
* it is called in a work_queue when switching to ad-hoc mode
* or in behalf of iwlist scan when the card is associated
* and root user ask for a scan.
- * the fucntion stop_scan should stop both the syncro and
+ * the function stop_scan should stop both the syncro and
* background scanning and can sleep.
- * The fucntion start_scan should initiate the background
+ * The function start_scan should initiate the background
* scanning and can't sleep.
*/
void (*scan_syncro)(struct net_device *dev);
* if the network does broadcast and the user did set essid
* check if essid match
* if the ap is not set, check that the user set the bssid
- * and the network does bradcast and that those two bssid match
+ * and the network does broadcast and that those two bssid match
*/
if ((apset && apmatch &&
((ssidset && ssidbroad && ssidmatch) ||
return 0;
}
-/* following are for a simplier TX queue management.
+/* following are for a simpler TX queue management.
* Instead of using netif_[stop/wake]_queue the driver
* will use these two functions (plus a reset one), that
* will internally use the kernel netif_* and takes
struct ieee80211_network * network, u16 type);
int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb);
- /* Softmac-generated frames (mamagement) are TXed via this
+ /* Softmac-generated frames (management) are TXed via this
* callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is
* not set. As some cards may have different HW queues that
* one might want to use for data and management frames
int (*handle_assoc_response) (struct net_device * dev, struct ieee80211_assoc_response_frame * resp, struct ieee80211_network * network);
- /* check whether Tx hw resouce available */
+ /* check whether Tx hw resource available */
short (*check_nic_enough_desc)(struct net_device *dev, int queue_index);
//added by wb for HT related
// void (*SwChnlByTimerHandler)(struct net_device *dev, int channel);
( apset && apmatch &&
((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
/* if the ap is not set, check that the user set the bssid
- * and the network does bradcast and that those two bssid matches
+ * and the network does broadcast and that those two bssid matches
*/
(!apset && ssidset && ssidbroad && ssidmatch)
){
/* until we do not set the state to IEEE80211_NOLINK
* there are no possibility to have someone else trying
- * to start an association procdure (we get here with
+ * to start an association procedure (we get here with
* ieee->state = IEEE80211_ASSOCIATING).
* When we set the state to IEEE80211_NOLINK it is possible
* that the RX path run an attempt to associate, but
/********************************************************************************************************************************
* This file is created to process BA Action Frame. According to 802.11 spec, there are 3 BA action types at all. And as BA is
- * related to TS, this part need some struture defined in QOS side code. Also TX RX is going to be resturctured, so how to send
+ * related to TS, this part need some structure defined in QOS side code. Also TX RX is going to be resturctured, so how to send
* ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
* WB 2008-05-27
* *****************************************************************************************************************************/
#define HT_OPMODE_MIXED 3
//
-// MIMO Power Save Setings
+// MIMO Power Save Settings
//
#define MIMO_PS_STATIC 0
#define MIMO_PS_DYNAMIC 1
u8 bEnableHT;
u8 bCurrentHTSupport;
- u8 bRegBW40MHz; // Tx 40MHz channel capablity
+ u8 bRegBW40MHz; // Tx 40MHz channel capability
u8 bCurBW40MHz; // Tx 40MHz channel capability
u8 bRegShortGI40MHz; // Tx Short GI for 40Mhz
u8 i=0;
- // filter out operational rate set not supported by AP, the lenth of it is 16
+ // filter out operational rate set not supported by AP, the length of it is 16
for(i=0;i<=15;i++){
pOperateMCS[i] = ieee->Regdot11HTOperationalRateSet[i]&pSupportMCS[i];
}
#define HT_OPMODE_MIXED 3
//
-// MIMO Power Save Setings
+// MIMO Power Save Settings
//
#define MIMO_PS_STATIC 0
#define MIMO_PS_DYNAMIC 1
#define bCCKRxIG 0x7f00
#define bCCKLNAPolarity 0x800000
#define bCCKRx1stGain 0x7f0000
-#define bCCKRFExtend 0x20000000 //CCK Rx inital gain polarity
+#define bCCKRFExtend 0x20000000 //CCK Rx initial gain polarity
#define bCCKRxAGCSatLevel 0x1f000000
#define bCCKRxAGCSatCount 0xe0
#define bCCKRxRFSettle 0x1f //AGCsamp_dly
#define RECV_BLK_SZ 512
#define RECV_BLK_CNT 16
#define RECV_BLK_TH RECV_BLK_CNT
-#define MAX_RECVBUF_SZ (30720) /* 30K */
+#define MAX_RECVBUF_SZ 9100
#define RECVBUFF_ALIGN_SZ 512
#define RSVD_ROOM_SZ (0)
/*These definition is used for Rx packet reordering.*/
#endif
#ifdef CONFIG_RTS5139_DEBUG
-static inline void rts51x_dump(u8 *buf, int buf_len)
-{
- int i;
- u8 tmp[16] = { 0 };
- u8 *_ptr = buf;
-
- for (i = 0; i < ((buf_len) / 16); i++) {
- RTS51X_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x %02x %02x %02x %02x\n",
- _ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4],
- _ptr[5], _ptr[6], _ptr[7], _ptr[8], _ptr[9],
- _ptr[10], _ptr[11], _ptr[12], _ptr[13], _ptr[14],
- _ptr[15]);
- _ptr += 16;
- }
- if ((buf_len) % 16) {
- memcpy(tmp, _ptr, (buf_len) % 16);
- _ptr = tmp;
- RTS51X_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x %02x %02x %02x %02x\n",
- _ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4],
- _ptr[5], _ptr[6], _ptr[7], _ptr[8], _ptr[9],
- _ptr[10], _ptr[11], _ptr[12], _ptr[13], _ptr[14],
- _ptr[15]);
- }
-}
-
-#define RTS51X_DUMP(buf, buf_len) \
- rts51x_dump((u8 *)(buf), (buf_len))
+#define RTS51X_DUMP(buf, buf_len) \
+ print_hex_dump(KERN_DEBUG, RTS51X_TIP, DUMP_PREFIX_NONE, \
+ 16, 1, (buf), (buf_len), false)
#define CATCH_TRIGGER(chip) \
do { \
#endif
#ifdef CONFIG_RTS_PSTOR_DEBUG
-static inline void rtsx_dump(u8 *buf, int buf_len)
-{
- int i;
- u8 tmp[16] = {0};
- u8 *_ptr = buf;
-
- for (i = 0; i < ((buf_len)/16); i++) {
- RTSX_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x %02x %02x %02x %02x\n",
- _ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4], _ptr[5],
- _ptr[6], _ptr[7], _ptr[8], _ptr[9], _ptr[10], _ptr[11],
- _ptr[12], _ptr[13], _ptr[14], _ptr[15]);
- _ptr += 16;
- }
- if ((buf_len) % 16) {
- memcpy(tmp, _ptr, (buf_len) % 16);
- _ptr = tmp;
- RTSX_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x %02x %02x %02x %02x\n",
- _ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4], _ptr[5],
- _ptr[6], _ptr[7], _ptr[8], _ptr[9], _ptr[10], _ptr[11],
- _ptr[12], _ptr[13], _ptr[14], _ptr[15]);
- }
-}
-
-#define RTSX_DUMP(buf, buf_len) rtsx_dump((u8 *)(buf), (buf_len))
-
+#define RTSX_DUMP(buf, buf_len) \
+ print_hex_dump(KERN_DEBUG, RTSX_STOR, DUMP_PREFIX_NONE, \
+ 16, 1, (buf), (buf_len), false)
#else
#define RTSX_DUMP(buf, buf_len)
#endif
qt_port->shadowLSR =
line_status & (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE |
SERIAL_LSR_BI);
- return;
}
static void ProcessModemStatus(struct quatech_port *qt_port,
qt_port->shadowMSR = modem_status;
wake_up_interruptible(&qt_port->wait);
- return;
}
static void ProcessRxChar(struct tty_struct *tty, struct usb_serial_port *port,
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __func__);
struct quatech_port *qt_port = qt_get_port_private(port);
- int retval = -ENODEV;
+ int retval;
if (!serial)
return -ENODEV;
struct usb_serial_port *port = tty->driver_data;
struct usb_serial *serial = get_usb_serial(port, __func__);
struct quatech_port *qt_port = qt_get_port_private(port);
- int retval = -ENODEV;
+ int retval;
if (!serial)
return -ENODEV;
qt_port->RxHolding = 1;
mutex_unlock(&qt_port->lock);
- return;
}
static void qt_unthrottle(struct tty_struct *tty)
}
}
mutex_unlock(&qt_port->lock);
- return;
-
}
static int qt_calc_num_ports(struct usb_serial *serial)
&& index <= MSG_FORMATTED_END)
&& !fmt_validate(speakup_default_msgs[index],
newstr)) {
+ kfree(newstr);
return -EINVAL;
}
spk_lock(flags);
Invalid pointer or handler.
[EEXIST]
- Attempted to create a channel manager when one already exists.
+ Attempted to create a channel manager when one already exists.
[EINVAL]
Invalid argument.
/* MBX_PM_MAX_RESOURCES: CORE 2 Clock Resources. */
#define MBX_CORE2_RESOURCES 1
-/* MBX_PM_MAX_RESOURCES: TOTAL Clock Reosurces. */
+/* MBX_PM_MAX_RESOURCES: TOTAL Clock Resources. */
#define MBX_PM_MAX_RESOURCES 11
/* Power Management Commands */
* The lower edge functions must be implemented by the Bridge driver
* writer, and are declared in chnl_sm.h.
*
- * Care is taken in this code to prevent simulataneous access to channel
+ * Care is taken in this code to prevent simultaneous access to channel
* queues from
* 1. Threads.
* 2. io_dpc(), scheduled from the io_isr() as an event.
* Channel Invariant:
* There is an important invariant condition which must be maintained per
* channel outside of bridge_chnl_get_ioc() and IO_Dispatch(), violation of
- * which may cause timeouts and/or failure offunction sync_wait_on_event.
+ * which may cause timeouts and/or failure of function sync_wait_on_event.
* This invariant condition is:
*
* list_empty(&pchnl->io_completions) ==> pchnl->sync_event is reset
/* Since DSPStream_Reclaim() does not take a timeout
* parameter, we pass the stream's timeout value to
* bridge_chnl_get_ioc. We cannot determine whether or not
- * we have waited in User mode. Since the stream's timeout
+ * we have waited in user mode. Since the stream's timeout
* value may be non-zero, we still have to set the event.
* Therefore, this optimization is taken out.
*
/*
* ======== io_dpc ========
* Deferred procedure call for shared memory channel driver ISR. Carries
- * out the dispatch of I/O as a non-preemptible event.It can only be
- * pre-empted by an ISR.
+ * out the dispatch of I/O as a non-preemptible event. It can only be
+ * pre-empted by an ISR.
*/
void io_dpc(unsigned long ref_data)
{
pio_mgr->intr_val);
}
}
- /* Proc-copy chanel dispatch */
+ /* Proc-copy channel dispatch */
input_chnl(pio_mgr, NULL, IO_SERVICE);
output_chnl(pio_mgr, NULL, IO_SERVICE);
/*
* ======== io_request_chnl ========
* Purpose:
- * Request chanenel I/O from the DSP. Sets flags in shared memory, then
+ * Request channel I/O from the DSP. Sets flags in shared memory, then
* interrupts the DSP.
*/
void io_request_chnl(struct io_mgr *io_manager, struct chnl_object *pchnl,
module_struct->num_sects);
/*
- * The section name strings start immedialty following
+ * The section name strings start immediately following
* the array of dll_sect structures.
*/
sect_str = (char *) &module_struct->
* @timeout timeout on waiting for the evetns.
* @pu_index index of the event set.
*
- * This functios will wait until any of the array element is set or until
+ * These functions will wait until any of the array element is set or until
* timeout. In case of success the function will return 0 and
* @pu_index will store the index of the array element set or in case
* of timeout the function will return -ETIME or in case of
ul_num_bytes, mem_type);
return status;
}
- /* copy the data from DSP memory, */
+ /* copy the data from DSP memory */
memcpy(host_buff, (void *)(dsp_base_addr + offset), ul_num_bytes);
return status;
}
pa_next = page_to_phys(page[0]);
while (!status && (i < num_pages)) {
/*
- * Reuse pa_next from the previous iteraion to avoid
+ * Reuse pa_next from the previous iteration to avoid
* an extra va2pa call
*/
pa_curr = pa_next;
dev_dbg(bridge, "OPP: %s IVA in sleep. No message to DSP\n");
return 0;
} else if ((dev_context->brd_state == BRD_RUNNING)) {
- /* Send a prenotificatio to DSP */
+ /* Send a prenotification to DSP */
dev_dbg(bridge, "OPP: %s sent notification to DSP\n", __func__);
sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_PRENOTIFY);
return 0;
* Description: Generate a trampoline symbol name (ASCII) using the value
* of the symbol. This places the new name into the user buffer.
* The name is fixed in length and of the form: __$dbTR__xxxxxxxx
- * (where "xxxxxxxx" is the hex value.
+ * (where "xxxxxxxx" is the hex value).
*/
static void priv_tramp_sym_gen_name(u32 value, char *dst)
{
/* Copy the symbol contents into the flat table */
*new_sym = cur_sym->sym_info;
- /* Now finaize the symbol. If it is in the tramp
+ /* Now finalize the symbol. If it is in the tramp
* section, we need to adjust for the section start.
* If it is external then we don't need to adjust at
* all.
int ret_val = 0;
struct tramp_img_dup_relo *dup_relo = NULL;
- /* Determinne if this image packet is already being tracked in the
+ /* Determine if this image packet is already being tracked in the
dup list for other trampolines. */
dup_pkt = priv_dup_find(dlthis, secnn, image_offset);
/*
* Function: dload_tramp_pkt_update
* Description: Update the duplicate copy of this image packet, which the
- * trampoline layer is already tracking. This is call is critical
+ * trampoline layer is already tracking. This call is critical
* to make if trampolines were generated anywhere within the
* packet and first pass relo continued on the remainder. The
* trampoline layer needs the updates image data so when 2nd
/* ----------------------------------- This */
#include <dspbridge/uuidutil.h>
-/*
- * ======== uuid_uuid_to_string ========
- * Purpose:
- * Converts a struct dsp_uuid to a string.
- * Note: snprintf format specifier is:
- * %[flags] [width] [.precision] [{h | l | I64 | L}]type
- */
-void uuid_uuid_to_string(struct dsp_uuid *uuid_obj, char *sz_uuid,
- s32 size)
-{
- s32 i; /* return result from snprintf. */
-
- i = snprintf(sz_uuid, size,
- "%.8X_%.4X_%.4X_%.2X%.2X_%.2X%.2X%.2X%.2X%.2X%.2X",
- uuid_obj->data1, uuid_obj->data2, uuid_obj->data3,
- uuid_obj->data4, uuid_obj->data5,
- uuid_obj->data6[0], uuid_obj->data6[1],
- uuid_obj->data6[2], uuid_obj->data6[3],
- uuid_obj->data6[4], uuid_obj->data6[5]);
-}
-
static s32 uuid_hex_to_bin(char *buf, s32 len)
{
s32 i;
* Type : hw_status
* Description : 0 -- No errors occurred
* RET_BAD_NULL_PARAM -- A Pointer
- * Paramater was set to NULL
+ * Parameter was set to NULL
*
* PURPOSE: : Flush the TLB entry pointed by the
* lock counter register
*
* Type : hw_status
* Description : 0 -- No errors occurred
- * RET_BAD_NULL_PARAM -- A Pointer Paramater
+ * RET_BAD_NULL_PARAM -- A Pointer Parameter
* was set to NULL
* RET_PARAM_OUT_OF_RANGE -- Input Parameter out
* of Range
*
* Type : hw_status
* Description : 0 -- No errors occurred
- * RET_BAD_NULL_PARAM -- A Pointer Paramater
+ * RET_BAD_NULL_PARAM -- A Pointer Parameter
* was set to NULL
* RET_PARAM_OUT_OF_RANGE -- Input Parameter
* out of Range
#define BRDIOCTL_POSTSCALE_NOTIFY (BRDIOCTL_PWRCONTROL + 0xA)
#define BRDIOCTL_CONSTRAINT_REQUEST (BRDIOCTL_PWRCONTROL + 0xB)
-/* Number of actual DSP-MMU TLB entrries */
+/* Number of actual DSP-MMU TLB entries */
#define BRDIOCTL_NUMOFMMUTLB 32
struct bridge_ioctl_extproc {
* mailbox interrupt's cmd value received. The class value are defined
* as a bit (10 thru 15) being set.
*
- * Note: Only 16 bits of each is used. Other 16 bit data reg available.
+ * Note: Only 16 bits of each is used. Other 16 bit data reg available.
*
* 16 bit Mbx bit defns:
*
* Parameters:
* noderes: Node resource info handle returned from
* node_allocate().
- * pr_ctxt: Poninter to process context data.
+ * pr_ctxt: Pointer to process context data.
* Returns:
* 0: Success.
* -EFAULT: Invalid hnode.
* ntfy_delete() - delete list of nofy events registered.
* @ntfy_obj: Pointer to the ntfy object structure.
*
- * This function is used to remove all the notify events registered.
+ * This function is used to remove all the notify events registered.
* unregister function is not needed in this function, to unregister
* a ntfy_event please look at ntfy_register function.
*
* Returns:
* 0 : Success.
* -EFAULT : Invalid processor handle.
- * -EPERM : General failure while retireving processor trace
+ * -EPERM : General failure while retrieving processor trace
* Buffer.
* Requires:
* pbuf is not NULL
* index: Stream index.
* pattr: Pointer to structure containing attributes to be
* applied to stream. Cannot be NULL.
- * strmres: Location to store stream resuorce info handle on output.
+ * strmres: Location to store stream resource info handle on output.
* Returns:
* 0: Success.
* -EFAULT: Invalid hnode.
* @event: events to wait for it.
* @timeout timeout on waiting for the evetn.
*
- * This functios will wait until @event is set or until timeout. In case of
+ * This function will wait until @event is set or until timeout. In case of
* success the function will return 0 and
* in case of timeout the function will return -ETIME
* in case of signal the function will return -ERESTARTSYS
* @timeout timeout on waiting for the evetns.
* @pu_index index of the event set.
*
- * This functios will wait until any of the array element is set or until
+ * This function will wait until any of the array element is set or until
* timeout. In case of success the function will return 0 and
* @pu_index will store the index of the array element set and in case
* of timeout the function will return -ETIME.
#define MAXUUIDLEN 37
-/*
- * ======== uuid_uuid_to_string ========
- * Purpose:
- * Converts a dsp_uuid to an ANSI string.
- * Parameters:
- * uuid_obj: Pointer to a dsp_uuid object.
- * sz_uuid: Pointer to a buffer to receive a NULL-terminated UUID
- * string.
- * size: Maximum size of the sz_uuid string.
- * Returns:
- * Requires:
- * uuid_obj & sz_uuid are non-NULL values.
- * Ensures:
- * Lenghth of sz_uuid is less than MAXUUIDLEN.
- * Details:
- * UUID string limit currently set at MAXUUIDLEN.
- */
-void uuid_uuid_to_string(struct dsp_uuid *uuid_obj, char *sz_uuid,
- s32 size);
-
/*
* ======== uuid_uuid_from_string ========
* Purpose:
struct dcd_manager *dcd_mgr_obj = hdcd_mgr; /* ptr to DCD mgr */
struct cod_libraryobj *lib = NULL;
int status = 0;
+ int len;
u32 ul_addr = 0; /* Used by cod_get_section */
u32 ul_len = 0; /* Used by cod_get_section */
u32 dw_buf_size; /* Used by REG functions */
char sz_reg_key[DCD_MAXPATHLENGTH];
char *sz_uuid; /*[MAXUUIDLEN]; */
+ char *tmp;
struct dcd_key_elem *dcd_key = NULL;
char sz_sect_name[MAXUUIDLEN + 2]; /* ".[UUID]\0" */
char *psz_coff_buf;
}
/* Create UUID value to set in registry. */
- uuid_uuid_to_string(obj_uuid, sz_uuid, MAXUUIDLEN);
+ snprintf(sz_uuid, MAXUUIDLEN, "%pUL", obj_uuid);
if ((strlen(sz_reg_key) + MAXUUIDLEN) < DCD_MAXPATHLENGTH)
strncat(sz_reg_key, sz_uuid, MAXUUIDLEN);
}
/* Ensure sz_uuid + 1 is not greater than sizeof sz_sect_name. */
+ len = strlen(sz_uuid);
+ if (len + 1 > sizeof(sz_sect_name)) {
+ status = -EPERM;
+ goto func_end;
+ }
/* Create section name based on node UUID. A period is
* pre-pended to the UUID string to form the section name.
* I.e. ".24BC8D90_BB45_11d4_B756_006008BDB66F" */
+
+ len -= 4; /* uuid has 4 delimiters '-' */
+ tmp = sz_uuid;
+
strncpy(sz_sect_name, ".", 2);
- strncat(sz_sect_name, sz_uuid, strlen(sz_uuid));
+ do {
+ char *uuid = strsep(&tmp, "-");
+ if (!uuid)
+ break;
+ len -= strlen(uuid);
+ strncat(sz_sect_name, uuid, strlen(uuid) + 1);
+ } while (len && strncat(sz_sect_name, "_", 2));
/* Get section information. */
status = cod_get_section(lib, sz_sect_name, &ul_addr, &ul_len);
status = cod_read_section(lib, sz_sect_name, psz_coff_buf, ul_len);
#endif
if (!status) {
- /* Compres DSP buffer to conform to PC format. */
+ /* Compress DSP buffer to conform to PC format. */
if (strstr(dcd_key->path, "iva") == NULL) {
compress_buf(psz_coff_buf, ul_len, DSPWORDSIZE);
} else {
status = -EPERM;
}
/* Create UUID value to find match in registry. */
- uuid_uuid_to_string(uuid_obj, sz_uuid, MAXUUIDLEN);
+ snprintf(sz_uuid, MAXUUIDLEN, "%pUL", uuid_obj);
if ((strlen(sz_reg_key) + MAXUUIDLEN) < DCD_MAXPATHLENGTH)
strncat(sz_reg_key, sz_uuid, MAXUUIDLEN);
else
} else {
status = -EPERM;
}
- uuid_uuid_to_string(uuid_obj, sz_uuid, MAXUUIDLEN);
+ snprintf(sz_uuid, MAXUUIDLEN, "%pUL", uuid_obj);
if ((strlen(sz_reg_key) + MAXUUIDLEN) < DCD_MAXPATHLENGTH)
strncat(sz_reg_key, sz_uuid, MAXUUIDLEN);
else
status = -EPERM;
/* Create UUID value to set in registry. */
- uuid_uuid_to_string(uuid_obj, sz_uuid, MAXUUIDLEN);
+ snprintf(sz_uuid, MAXUUIDLEN, "%pUL", uuid_obj);
if ((strlen(sz_reg_key) + MAXUUIDLEN) < DCD_MAXPATHLENGTH)
strncat(sz_reg_key, sz_uuid, MAXUUIDLEN);
else
#endif
};
-static int __init bridge_init(void)
-{
- return platform_driver_register(&bridge_driver);
-}
-
-static void __exit bridge_exit(void)
-{
- platform_driver_unregister(&bridge_driver);
-}
-
/* To remove all process resources before removing the process from the
* process context list */
int drv_remove_all_resources(void *process_ctxt)
return status;
}
-/* Bridge driver initialization and de-initialization functions */
-module_init(bridge_init);
-module_exit(bridge_exit);
+module_platform_driver(bridge_driver);
/* Unwind whatever was loaded */
if (status) {
- /* irrespective of the status of dev_remove_device we conitinue
+ /* irrespective of the status of dev_remove_device we continue
* unloading. Get the Driver Object iterate through and remove.
* Reset the status to E_FAIL to avoid going through
* api_init_complete2. */
func_cont:
/* Attempt to Start the Board */
if (!status) {
- /* BRD_AutoStart could fail if the dsp execuetable is not the
+ /* BRD_AutoStart could fail if the dsp executable is not the
* correct one. We should not propagate that error
* into the device loader. */
(void)api_init_complete2();
IVAPROCTYPE_ARM7)
proc_detect = true;
}
- /* User applciatiuons aonly check for chip type, so
- * this clumsy overwrite */
+ /* User applications only check for chip type, so
+ * this is a clumsy overwrite */
processor_info->processor_type = DSPTYPE64;
} else {
dev_dbg(bridge, "%s: Failed to get DCD processor info "
nldr_obj->ovly_table[i].execute_sects++;
} else {
- /* Put in "other" sectins */
+ /* Put in "other" sections */
status =
add_ovly_sect(nldr_obj,
&nldr_obj->
return -EFAULT;
hnode_mgr = hnode->node_mgr;
- /* Enter hnode_mgr critical section (since we're accessing
+ /* Enter hnode_mgr critical section since we're accessing
* data that could be changed by node_change_priority() and
* node_connect(). */
mutex_lock(&hnode_mgr->node_mgr_lock);
hnode->ntype = node_type = pndb_props->ntype;
/* Create UUID value to set in registry. */
- uuid_uuid_to_string((struct dsp_uuid *)node_uuid, sz_uuid,
- MAXUUIDLEN);
+ snprintf(sz_uuid, MAXUUIDLEN, "%pUL", node_uuid);
dev_dbg(bridge, "(node) UUID: %s\n", sz_uuid);
/* Fill in message args that come from NDB */
if (status)
goto func_end;
- /* If we made it this far, create the Proceesor object: */
+ /* If we made it this far, create the Processor object: */
p_proc_object = kzalloc(sizeof(struct proc_object), GFP_KERNEL);
/* Fill out the Processor Object: */
if (p_proc_object == NULL) {
* eventually reassigned to the device as far as driver matching
* condition is kept.
*
- * Unfortunatelly, an existing usbip connection will be dropped
+ * Unfortunately, an existing usbip connection will be dropped
* due to this driver unbinding. So, skip here.
* A user may need to set a special configuration value before
* exporting the device.
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/stat.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <net/sock.h>
#include "usbip_common.h"
unsigned long usbip_debug_flag;
#endif
EXPORT_SYMBOL_GPL(usbip_debug_flag);
+module_param(usbip_debug_flag, ulong, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(usbip_debug_flag, "debug flags (defined in usbip_common.h)");
/* FIXME */
struct device_attribute dev_attr_usbip_debug;
[AS_HELP_STRING([--with-tcp-wrappers],
[use the libwrap (TCP wrappers) library])],
dnl [ACTION-IF-GIVEN]
- [saved_LIBS="$LIBS"
- if test "$withval" = "yes"; then
+ [if test "$withval" = "yes"; then
AC_MSG_RESULT([yes])
AC_MSG_CHECKING([for hosts_access in -lwrap])
- LIBS="-lwrap $LIBS"
+ saved_LIBS="$LIBS"
+ LIBS="-lwrap $saved_LIBS"
AC_TRY_LINK(
[int hosts_access(); int allow_severity, deny_severity;],
[hosts_access()],
[use tcp wrapper]) wrap_LIB="-lwrap"],
[AC_MSG_RESULT([not found]); exit 1])
else
- AC_MSG_RESULT([no])
- fi
- LIBS="$saved_LIBS"],
+ AC_MSG_RESULT([no]);
+ LIBS="$saved_LIBS"
+ fi],
dnl [ACTION-IF-NOT-GIVEN]
[AC_MSG_RESULT([(default)])
AC_MSG_CHECKING([for hosts_access in -lwrap])
usbip \- manage USB/IP devices
.SH SYNOPSIS
.B usbip
-[\fIoptions\fR]
+[\foptions\R] <\fIcommand\fR> <\fIargs\fR>
.SH DESCRIPTION
-Devices exported by USB/IP servers can be listed, attached and
-detached using this program.
+On a USB/IP server, devices can be listed, bound, and unbound using
+this program. On a USB/IP client, devices exported by USB/IP servers
+can be listed, attached and detached.
.SH OPTIONS
.HP
-\fB\-a\fR, \fB\-\-attach\fR <host> <bus_id>
+\fB\-\-debug\fR
.IP
-Attach a remote USB device.
+Print debugging information.
+.PP
+
+.HP
+\fB\-\-log\fR
+.IP
+Log to syslog.
+.PP
+
+.SH COMMANDS
+.HP
+\fBversion\fR
+.IP
+Show version and exit.
.PP
.HP
-\fB\-x\fR, \fB\-\-attachall\fR <host>
+\fBhelp\fR [\fIcommand\fR]
.IP
-Attach all remote USB devices on the specific host.
+Print the program help message, or help on a specific command, and
+then exit.
.PP
.HP
-\fB\-d\fR, \fB\-\-detach\fR <ports>
+\fBattach\fR \-\-host=<\fIhost\fR> \-\-busid=<\fIbus_id\fR>
+.IP
+Attach a remote USB device.
+.PP
+
+.HP
+\fBdetach\fR \-\-port=<\fIport\fR>
.IP
Detach an imported USB device.
.PP
.HP
-\fB\-l\fR, \fB\-\-list\fR <hosts>
+\fBbind\fR \-\-busid=<\fIbusid\fR>
.IP
-List exported USB devices.
+Make a device exportable.
.PP
.HP
-\fB\-p\fR, \fB\-\-port\fR
+\fBunbind\fR \-\-busid=<\fIbusid\fR>
.IP
-List virtual USB port status.
+Stop exporting a device so it can be used by a local driver.
.PP
.HP
-\fB\-D\fR, \fB\-\-debug\fR
+\fBlist\fR \-\-remote=<\fIhost\fR>
.IP
-Print debugging information.
+List USB devices exported by a remote host.
.PP
.HP
-\fB\-v\fR, \fB\-\-version\fR
+\fBlist\fR \-\-local
.IP
-Show version.
+List local USB devices.
.PP
+
.SH EXAMPLES
- client:# usbip --list server
+ client:# usbip list --remote=server
- List exportable usb devices on the server.
- client:# usbip --attach server 1-2
+ client:# usbip attach --host=server --busid=1-2
- Connect the remote USB device.
- client:# usbip --port
- - Show virtual port status.
-
- client:# usbip --detach 0
+ client:# usbip detach --port=0
- Detach the usb device.
.SH "SEE ALSO"
-\fBusbipd\fP\fB(8)\fB\fP,
-\fBusbip_attach_driver\fP\fB(8)\fB\fP
+\fBusbipd\fP\fB(8)\fB\fP
+++ /dev/null
-.TH USBIP_BIND_DRIVER "8" "February 2009" "usbip" "System Administration Utilities"
-.SH NAME
-usbip_bind_driver \- change driver binding for USB/IP
-
-.SH SYNOPSIS
-.B usbip_bind_driver
-[\fIoptions\fR]
-
-.SH DESCRIPTION
-Driver bindings for USB devices can be changed using
-this program. It is used to export and unexport USB
-devices over USB/IP.
-
-.SH OPTIONS
-.TP
-\fB\-u\fR, \fB\-\-usbip\fR <busid>
-Make a device exportable
-.TP
-\fB\-o\fR, \fB\-\-other\fR <busid>
-Use a device by a local driver
-.TP
-\fB\-l\fR, \fB\-\-list\fR
-Print usb devices and their drivers
-.TP
-\fB\-L\fR, \fB\-\-list2\fR
-Print usb devices and their drivers in parseable mode
-
-.SH EXAMPLES
-
- server:# usbip_bind_driver --list
- - List driver assignments for usb devices.
-
- server:# usbip_bind_driver --usbip 1-2
- - Bind usbip-host.ko to the device of busid 1-2.
- - A usb device 1-2 is now exportable to other hosts!
-
- server:# usbip_bind_driver --other 1-2
- - Shutdown exporting and use the device locally.
-
-.SH "SEE ALSO"
-\fBusbip\fP\fB(8)\fB\fP,
-\fBusbipd\fP\fB(8)\fB\fP
provides USB/IP clients access to exported USB devices.
Devices have to explicitly be exported using
-.B usbip_bind_driver
+.B usbip bind
before usbipd makes them available to other hosts.
The daemon accepts connections from USB/IP clients
Print debugging information.
.PP
+\fB\-h\fR, \fB\-\-help\fR
+.IP
+Print the program help message and exit.
+.PP
+
.HP
\fB\-v\fR, \fB\-\-version\fR
.IP
server:# usbipd -D
- Start usbip daemon.
- server:# usbip_bind_driver --list
+ server:# usbip list --local
- List driver assignments for usb devices.
- server:# usbip_bind_driver --usbip 1-2
+ server:# usbip bind --busid=1-2
- Bind usbip-host.ko to the device of busid 1-2.
- A usb device 1-2 is now exportable to other hosts!
- - Use 'usbip_bind_driver --other 1-2' when you want to shutdown exporting and use the device locally.
+ - Use 'usbip unbind --busid=1-2' when you want to shutdown exporting and use the device locally.
.SH "SEE ALSO"
-\fBusbip\fP\fB(8)\fB\fP,
-\fBusbip_attach_driver\fP\fB(8)\fB\fP
+\fBusbip\fP\fB(8)\fB\fP
* disable endpoints. pending urbs are unlinked(dequeued).
*
* NOTE: After calling rh_port_disconnect(), the USB device drivers of a
- * deteched device should release used urbs in a cleanup function(i.e.
+ * detached device should release used urbs in a cleanup function (i.e.
* xxx_disconnect()). Therefore, vhci_hcd does not need to release
* pushed urbs and their private data in this function.
*
- * NOTE: vhci_dequeue() must be considered carefully. When shutdowning
+ * NOTE: vhci_dequeue() must be considered carefully. When shutting down
* a connection, vhci_shutdown_connection() expects vhci_dequeue()
* gives back pushed urbs and frees their private data by request of
* the cleanup function of a USB driver. When unlinking a urb with an
*
* However the VME driver at http://www.vmelinux.org/ is rather old and doesn't
* even support the tsi148 chipset (which has 8 master and 8 slave windows).
- * We'll run with this or now as far as possible, however it probably makes
+ * We'll run with this for now as far as possible, however it probably makes
* sense to get rid of the old mappings and just do everything dynamically.
*
* So for now, we'll restrict the driver to providing 4 masters and 4 slaves as
* defined above and try to support at least some of the interface from
- * http://www.vmelinux.org/ as an alternative drive can be written providing a
- * saner interface later.
+ * http://www.vmelinux.org/ as an alternative the driver can be written
+ * providing a saner interface later.
*
* The vmelinux.org driver never supported slave images, the devices reserved
* for slaves were repurposed to support all 8 master images on the UniverseII!
}
/*
- * We are going ot alloc a page during init per window for small transfers.
+ * We are going to alloc a page during init per window for small transfers.
* Small transfers will go user space -> buffer -> VME. Larger (more than a
* page) transfers will lock the user space buffer into memory and then
* transfer the data directly from the user space buffers out to VME.
pMgmt->abyIBSSSuppRates[3] |= BIT7;
}
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %x %x %x %x\n",
- pMgmt->abyIBSSSuppRates[2],
- pMgmt->abyIBSSSuppRates[3],
- pMgmt->abyIBSSSuppRates[4],
- pMgmt->abyIBSSSuppRates[5]);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %*ph\n",
+ 4, pMgmt->abyIBSSSuppRates + 2);
netif_stop_queue(pDevice->dev);
spin_lock_irq(&pDevice->lock);
break;
case VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR \n");
- return -EOPNOTSUPP;
- break;
+ ret = -EOPNOTSUPP;
+ goto out;
case VIAWGET_HOSTAPD_FLUSH:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_FLUSH \n");
spin_lock_irq(&pDevice->lock);
case VIAWGET_HOSTAPD_STA_CLEAR_STATS:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_STA_CLEAR_STATS \n");
- return -EOPNOTSUPP;
-
+ ret = -EOPNOTSUPP;
+ goto out;
default:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "vt6656_hostap_ioctl: unknown cmd=%d\n",
(int)param->cmd);
- return -EOPNOTSUPP;
- break;
+ ret = -EOPNOTSUPP;
+ goto out;
}
pMgmt->abyIBSSSuppRates[3] |= BIT7;
}
- DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %x %x %x %x\n",
- pMgmt->abyIBSSSuppRates[2],
- pMgmt->abyIBSSSuppRates[3],
- pMgmt->abyIBSSSuppRates[4],
- pMgmt->abyIBSSSuppRates[5]);
+ DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Support Rate= %*ph\n",
+ 4, pMgmt->abyIBSSSuppRates + 2);
netif_stop_queue(pDevice->dev);
spin_lock_irq(&pDevice->lock);
* Date: Feb. 19, 2004
*
* Functions:
- * IFRFbWriteEmbeded - Embeded write RF register via MAC
+ * IFRFbWriteEmbeded - Embedded write RF register via MAC
*
* Revision History:
*
/*--------------------- Export Functions --------------------------*/
/*
- * Description: Write to IF/RF, by embeded programming
+ * Description: Write to IF/RF, by embedded programming
*
* Parameters:
* In:
uRTSFrameLen -= 4;
}
- // Note: So far RTSHead dosen't appear in ATIM & Beacom DMA, so we don't need to take them into account.
+ // Note: So far RTSHead doesn't appear in ATIM & Beacom DMA, so we don't need to take them into account.
// Otherwise, we need to modified codes for them.
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
if (byFBOption == AUTO_FB_NONE) {
pMgmt->abyPSTxMap[0] |= byMask[0];
return 0;
}
- // muticast/broadcast data rate
+ // multicast/broadcast data rate
if (pDevice->byBBType != BB_TYPE_11A)
pDevice->wCurrentRate = RATE_2M;
pDevice->nTxDataTimeCout = 0;
}
else {
- // printk("mike:-->First time triger TimerTxData InSleep\n");
+ // printk("mike:-->First time trigger TimerTxData InSleep\n");
}
pDevice->IsTxDataTrigger = TRUE;
add_timer(&pDevice->sTimerTxData);
* bMgrPrepareBeaconToSend - Prepare Beacon frame
* s_vMgrLogStatus - Log 802.11 Status
* vMgrRxManagePacket - Rcv management frame dispatch function
- * s_vMgrFormatTIM- Assember TIM field of beacon
+ * s_vMgrFormatTIM- Assembler TIM field of beacon
* vMgrTimerInit- Initial 1-sec and command call back funtions
*
* Revision History:
}
//
- // Preamble may change dynamiclly
+ // Preamble may change dynamically
//
byOldPreambleType = pDevice->byPreambleType;
if (WLAN_GET_CAP_INFO_SHORTPREAMBLE(pBSSList->wCapInfo)) {
if (pDevice->byPreambleType != byOldPreambleType)
CARDvSetRSPINF(pDevice, (BYTE)pDevice->byBBType);
//
- // Basic Rate Set may change dynamiclly
+ // Basic Rate Set may change dynamically
//
if (pBSSList->eNetworkTypeInUse == PHY_TYPE_11B) {
uRateLen = WLAN_RATES_MAXLEN_11B;
return -1;
#ifdef WEP_DEBUG
- printk(KERN_DEBUG
- "WEP key %d len %d = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
- keynum, keylen, key[0], key[1], key[2], key[3], key[4], key[5],
- key[6], key[7]);
+ printk(KERN_DEBUG "WEP key %d len %d = %*phC\n", keynum, keylen,
+ 8, key);
#endif
wlandev->wep_keylens[keynum] = keylen;
keylen += 3; /* add in IV bytes */
#ifdef WEP_DEBUG
- printk(KERN_DEBUG
- "D %d: %02x %02x %02x (%d %d) %02x:%02x:%02x:%02x:%02x\n", len,
- key[0], key[1], key[2], keyidx, keylen, key[3], key[4], key[5],
- key[6], key[7]);
+ printk(KERN_DEBUG "D %d: %*ph (%d %d) %*phC\n", len, 3, key,
+ keyidx, keylen, 5, key + 3);
#endif
/* set up the RC4 state */
keylen += 3; /* add in IV bytes */
#ifdef WEP_DEBUG
- printk(KERN_DEBUG
- "E %d (%d/%d %d) %02x %02x %02x %02x:%02x:%02x:%02x:%02x\n", len,
- iv[3], keynum, keylen, key[0], key[1], key[2], key[3], key[4],
- key[5], key[6], key[7]);
+ printk(KERN_DEBUG "E %d (%d/%d %d) %*ph %*phC\n", len,
+ iv[3], keynum, keylen, 3, key, 5, key + 3);
#endif
/* set up the RC4 state */
}
if ((filter >= 0) && (filter <= 7)) {
- pr_debug("FilterTable[%d]-%d: %02x %02x %02x %02x\n",
+ pr_debug("FilterTable[%d]-%d: %*ph\n",
filter_tb, filter,
- XGI_TV_filter[filter_tb].
- filter[filter][0],
- XGI_TV_filter[filter_tb].
- filter[filter][1],
- XGI_TV_filter[filter_tb].
- filter[filter][2],
- XGI_TV_filter[filter_tb].
- filter[filter][3]
- );
+ 4, XGI_TV_filter[filter_tb].
+ filter[filter]);
xgifb_reg_set(
XGIPART2,
0x35,
if (temp <= 2)
temp &= 0x03;
else
- temp = ((temp & 0x04) >> 1) || ((~temp) & 0x01);
+ temp = ((temp & 0x04) >> 1) | ((~temp) & 0x01);
xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
#include <linux/cpumask.h>
#include <linux/cpu.h>
#include <linux/vmalloc.h>
+#include <linux/hardirq.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
#include "zsmalloc.h"
-#include "zsmalloc_int.h"
+
+/*
+ * This must be power of 2 and greater than of equal to sizeof(link_free).
+ * These two conditions ensure that any 'struct link_free' itself doesn't
+ * span more than 1 page which avoids complex case of mapping 2 pages simply
+ * to restore link_free pointer values.
+ */
+#define ZS_ALIGN 8
+
+/*
+ * A single 'zspage' is composed of up to 2^N discontiguous 0-order (single)
+ * pages. ZS_MAX_ZSPAGE_ORDER defines upper limit on N.
+ */
+#define ZS_MAX_ZSPAGE_ORDER 2
+#define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_ZSPAGE_ORDER)
+
+/*
+ * Object location (<PFN>, <obj_idx>) is encoded as
+ * as single (void *) handle value.
+ *
+ * Note that object index <obj_idx> is relative to system
+ * page <PFN> it is stored in, so for each sub-page belonging
+ * to a zspage, obj_idx starts with 0.
+ *
+ * This is made more complicated by various memory models and PAE.
+ */
+
+#ifndef MAX_PHYSMEM_BITS
+#ifdef CONFIG_HIGHMEM64G
+#define MAX_PHYSMEM_BITS 36
+#else /* !CONFIG_HIGHMEM64G */
+/*
+ * If this definition of MAX_PHYSMEM_BITS is used, OBJ_INDEX_BITS will just
+ * be PAGE_SHIFT
+ */
+#define MAX_PHYSMEM_BITS BITS_PER_LONG
+#endif
+#endif
+#define _PFN_BITS (MAX_PHYSMEM_BITS - PAGE_SHIFT)
+#define OBJ_INDEX_BITS (BITS_PER_LONG - _PFN_BITS)
+#define OBJ_INDEX_MASK ((_AC(1, UL) << OBJ_INDEX_BITS) - 1)
+
+#define MAX(a, b) ((a) >= (b) ? (a) : (b))
+/* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */
+#define ZS_MIN_ALLOC_SIZE \
+ MAX(32, (ZS_MAX_PAGES_PER_ZSPAGE << PAGE_SHIFT >> OBJ_INDEX_BITS))
+#define ZS_MAX_ALLOC_SIZE PAGE_SIZE
+
+/*
+ * On systems with 4K page size, this gives 254 size classes! There is a
+ * trader-off here:
+ * - Large number of size classes is potentially wasteful as free page are
+ * spread across these classes
+ * - Small number of size classes causes large internal fragmentation
+ * - Probably its better to use specific size classes (empirically
+ * determined). NOTE: all those class sizes must be set as multiple of
+ * ZS_ALIGN to make sure link_free itself never has to span 2 pages.
+ *
+ * ZS_MIN_ALLOC_SIZE and ZS_SIZE_CLASS_DELTA must be multiple of ZS_ALIGN
+ * (reason above)
+ */
+#define ZS_SIZE_CLASS_DELTA 16
+#define ZS_SIZE_CLASSES ((ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE) / \
+ ZS_SIZE_CLASS_DELTA + 1)
+
+/*
+ * We do not maintain any list for completely empty or full pages
+ */
+enum fullness_group {
+ ZS_ALMOST_FULL,
+ ZS_ALMOST_EMPTY,
+ _ZS_NR_FULLNESS_GROUPS,
+
+ ZS_EMPTY,
+ ZS_FULL
+};
+
+/*
+ * We assign a page to ZS_ALMOST_EMPTY fullness group when:
+ * n <= N / f, where
+ * n = number of allocated objects
+ * N = total number of objects zspage can store
+ * f = 1/fullness_threshold_frac
+ *
+ * Similarly, we assign zspage to:
+ * ZS_ALMOST_FULL when n > N / f
+ * ZS_EMPTY when n == 0
+ * ZS_FULL when n == N
+ *
+ * (see: fix_fullness_group())
+ */
+static const int fullness_threshold_frac = 4;
+
+struct size_class {
+ /*
+ * Size of objects stored in this class. Must be multiple
+ * of ZS_ALIGN.
+ */
+ int size;
+ unsigned int index;
+
+ /* Number of PAGE_SIZE sized pages to combine to form a 'zspage' */
+ int pages_per_zspage;
+
+ spinlock_t lock;
+
+ /* stats */
+ u64 pages_allocated;
+
+ struct page *fullness_list[_ZS_NR_FULLNESS_GROUPS];
+};
+
+/*
+ * Placed within free objects to form a singly linked list.
+ * For every zspage, first_page->freelist gives head of this list.
+ *
+ * This must be power of 2 and less than or equal to ZS_ALIGN
+ */
+struct link_free {
+ /* Handle of next free chunk (encodes <PFN, obj_idx>) */
+ void *next;
+};
+
+struct zs_pool {
+ struct size_class size_class[ZS_SIZE_CLASSES];
+
+ gfp_t flags; /* allocation flags used when growing pool */
+ const char *name;
+};
/*
* A zspage's class index and fullness group
#define CLASS_IDX_MASK ((1 << CLASS_IDX_BITS) - 1)
#define FULLNESS_MASK ((1 << FULLNESS_BITS) - 1)
+/*
+ * By default, zsmalloc uses a copy-based object mapping method to access
+ * allocations that span two pages. However, if a particular architecture
+ * 1) Implements local_flush_tlb_kernel_range() and 2) Performs VM mapping
+ * faster than copying, then it should be added here so that
+ * USE_PGTABLE_MAPPING is defined. This causes zsmalloc to use page table
+ * mapping rather than copying
+ * for object mapping.
+*/
+#if defined(CONFIG_ARM)
+#define USE_PGTABLE_MAPPING
+#endif
+
+struct mapping_area {
+#ifdef USE_PGTABLE_MAPPING
+ struct vm_struct *vm; /* vm area for mapping object that span pages */
+#else
+ char *vm_buf; /* copy buffer for objects that span pages */
+#endif
+ char *vm_addr; /* address of kmap_atomic()'ed pages */
+ enum zs_mapmode vm_mm; /* mapping mode */
+};
+
+
/* per-cpu VM mapping areas for zspage accesses that cross page boundaries */
static DEFINE_PER_CPU(struct mapping_area, zs_map_area);
return page;
}
-static void zs_copy_map_object(char *buf, struct page *firstpage,
- int off, int size)
+#ifdef USE_PGTABLE_MAPPING
+static inline int __zs_cpu_up(struct mapping_area *area)
+{
+ /*
+ * Make sure we don't leak memory if a cpu UP notification
+ * and zs_init() race and both call zs_cpu_up() on the same cpu
+ */
+ if (area->vm)
+ return 0;
+ area->vm = alloc_vm_area(PAGE_SIZE * 2, NULL);
+ if (!area->vm)
+ return -ENOMEM;
+ return 0;
+}
+
+static inline void __zs_cpu_down(struct mapping_area *area)
+{
+ if (area->vm)
+ free_vm_area(area->vm);
+ area->vm = NULL;
+}
+
+static inline void *__zs_map_object(struct mapping_area *area,
+ struct page *pages[2], int off, int size)
+{
+ BUG_ON(map_vm_area(area->vm, PAGE_KERNEL, &pages));
+ area->vm_addr = area->vm->addr;
+ return area->vm_addr + off;
+}
+
+static inline void __zs_unmap_object(struct mapping_area *area,
+ struct page *pages[2], int off, int size)
+{
+ unsigned long addr = (unsigned long)area->vm_addr;
+ unsigned long end = addr + (PAGE_SIZE * 2);
+
+ flush_cache_vunmap(addr, end);
+ unmap_kernel_range_noflush(addr, PAGE_SIZE * 2);
+ local_flush_tlb_kernel_range(addr, end);
+}
+
+#else /* USE_PGTABLE_MAPPING */
+
+static inline int __zs_cpu_up(struct mapping_area *area)
+{
+ /*
+ * Make sure we don't leak memory if a cpu UP notification
+ * and zs_init() race and both call zs_cpu_up() on the same cpu
+ */
+ if (area->vm_buf)
+ return 0;
+ area->vm_buf = (char *)__get_free_page(GFP_KERNEL);
+ if (!area->vm_buf)
+ return -ENOMEM;
+ return 0;
+}
+
+static inline void __zs_cpu_down(struct mapping_area *area)
+{
+ if (area->vm_buf)
+ free_page((unsigned long)area->vm_buf);
+ area->vm_buf = NULL;
+}
+
+static void *__zs_map_object(struct mapping_area *area,
+ struct page *pages[2], int off, int size)
{
- struct page *pages[2];
int sizes[2];
void *addr;
+ char *buf = area->vm_buf;
- pages[0] = firstpage;
- pages[1] = get_next_page(firstpage);
- BUG_ON(!pages[1]);
+ /* disable page faults to match kmap_atomic() return conditions */
+ pagefault_disable();
+
+ /* no read fastpath */
+ if (area->vm_mm == ZS_MM_WO)
+ goto out;
sizes[0] = PAGE_SIZE - off;
sizes[1] = size - sizes[0];
addr = kmap_atomic(pages[1]);
memcpy(buf + sizes[0], addr, sizes[1]);
kunmap_atomic(addr);
+out:
+ return area->vm_buf;
}
-static void zs_copy_unmap_object(char *buf, struct page *firstpage,
- int off, int size)
+static void __zs_unmap_object(struct mapping_area *area,
+ struct page *pages[2], int off, int size)
{
- struct page *pages[2];
int sizes[2];
void *addr;
+ char *buf = area->vm_buf;
- pages[0] = firstpage;
- pages[1] = get_next_page(firstpage);
- BUG_ON(!pages[1]);
+ /* no write fastpath */
+ if (area->vm_mm == ZS_MM_RO)
+ goto out;
sizes[0] = PAGE_SIZE - off;
sizes[1] = size - sizes[0];
addr = kmap_atomic(pages[1]);
memcpy(addr, buf + sizes[0], sizes[1]);
kunmap_atomic(addr);
+
+out:
+ /* enable page faults to match kunmap_atomic() return conditions */
+ pagefault_enable();
}
+#endif /* USE_PGTABLE_MAPPING */
+
static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action,
void *pcpu)
{
- int cpu = (long)pcpu;
+ int ret, cpu = (long)pcpu;
struct mapping_area *area;
switch (action) {
case CPU_UP_PREPARE:
area = &per_cpu(zs_map_area, cpu);
- /*
- * Make sure we don't leak memory if a cpu UP notification
- * and zs_init() race and both call zs_cpu_up() on the same cpu
- */
- if (area->vm_buf)
- return 0;
- area->vm_buf = (char *)__get_free_page(GFP_KERNEL);
- if (!area->vm_buf)
- return -ENOMEM;
- return 0;
+ ret = __zs_cpu_up(area);
+ if (ret)
+ return notifier_from_errno(ret);
break;
case CPU_DEAD:
case CPU_UP_CANCELED:
area = &per_cpu(zs_map_area, cpu);
- if (area->vm_buf)
- free_page((unsigned long)area->vm_buf);
- area->vm_buf = NULL;
+ __zs_cpu_down(area);
break;
}
enum fullness_group fg;
struct size_class *class;
struct mapping_area *area;
+ struct page *pages[2];
BUG_ON(!handle);
+ /*
+ * Because we use per-cpu mapping areas shared among the
+ * pools/users, we can't allow mapping in interrupt context
+ * because it can corrupt another users mappings.
+ */
+ BUG_ON(in_interrupt());
+
obj_handle_to_location(handle, &page, &obj_idx);
get_zspage_mapping(get_first_page(page), &class_idx, &fg);
class = &pool->size_class[class_idx];
off = obj_idx_to_offset(page, obj_idx, class->size);
area = &get_cpu_var(zs_map_area);
+ area->vm_mm = mm;
if (off + class->size <= PAGE_SIZE) {
/* this object is contained entirely within a page */
area->vm_addr = kmap_atomic(page);
return area->vm_addr + off;
}
- /* disable page faults to match kmap_atomic() return conditions */
- pagefault_disable();
+ /* this object spans two pages */
+ pages[0] = page;
+ pages[1] = get_next_page(page);
+ BUG_ON(!pages[1]);
- if (mm != ZS_MM_WO)
- zs_copy_map_object(area->vm_buf, page, off, class->size);
- area->vm_addr = NULL;
- return area->vm_buf;
+ return __zs_map_object(area, pages, off, class->size);
}
EXPORT_SYMBOL_GPL(zs_map_object);
struct size_class *class;
struct mapping_area *area;
- area = &__get_cpu_var(zs_map_area);
- /* single-page object fastpath */
- if (area->vm_addr) {
- kunmap_atomic(area->vm_addr);
- goto out;
- }
-
- /* no write fastpath */
- if (area->vm_mm == ZS_MM_RO)
- goto pfenable;
-
BUG_ON(!handle);
obj_handle_to_location(handle, &page, &obj_idx);
class = &pool->size_class[class_idx];
off = obj_idx_to_offset(page, obj_idx, class->size);
- zs_copy_unmap_object(area->vm_buf, page, off, class->size);
+ area = &__get_cpu_var(zs_map_area);
+ if (off + class->size <= PAGE_SIZE)
+ kunmap_atomic(area->vm_addr);
+ else {
+ struct page *pages[2];
-pfenable:
- /* enable page faults to match kunmap_atomic() return conditions */
- pagefault_enable();
-out:
+ pages[0] = page;
+ pages[1] = get_next_page(page);
+ BUG_ON(!pages[1]);
+
+ __zs_unmap_object(area, pages, off, class->size);
+ }
put_cpu_var(zs_map_area);
}
EXPORT_SYMBOL_GPL(zs_unmap_object);
+++ /dev/null
-/*
- * zsmalloc memory allocator
- *
- * Copyright (C) 2011 Nitin Gupta
- *
- * This code is released using a dual license strategy: BSD/GPL
- * You can choose the license that better fits your requirements.
- *
- * Released under the terms of 3-clause BSD License
- * Released under the terms of GNU General Public License Version 2.0
- */
-
-#ifndef _ZS_MALLOC_INT_H_
-#define _ZS_MALLOC_INT_H_
-
-#include <linux/kernel.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-/*
- * This must be power of 2 and greater than of equal to sizeof(link_free).
- * These two conditions ensure that any 'struct link_free' itself doesn't
- * span more than 1 page which avoids complex case of mapping 2 pages simply
- * to restore link_free pointer values.
- */
-#define ZS_ALIGN 8
-
-/*
- * A single 'zspage' is composed of up to 2^N discontiguous 0-order (single)
- * pages. ZS_MAX_ZSPAGE_ORDER defines upper limit on N.
- */
-#define ZS_MAX_ZSPAGE_ORDER 2
-#define ZS_MAX_PAGES_PER_ZSPAGE (_AC(1, UL) << ZS_MAX_ZSPAGE_ORDER)
-
-/*
- * Object location (<PFN>, <obj_idx>) is encoded as
- * as single (void *) handle value.
- *
- * Note that object index <obj_idx> is relative to system
- * page <PFN> it is stored in, so for each sub-page belonging
- * to a zspage, obj_idx starts with 0.
- *
- * This is made more complicated by various memory models and PAE.
- */
-
-#ifndef MAX_PHYSMEM_BITS
-#ifdef CONFIG_HIGHMEM64G
-#define MAX_PHYSMEM_BITS 36
-#else /* !CONFIG_HIGHMEM64G */
-/*
- * If this definition of MAX_PHYSMEM_BITS is used, OBJ_INDEX_BITS will just
- * be PAGE_SHIFT
- */
-#define MAX_PHYSMEM_BITS BITS_PER_LONG
-#endif
-#endif
-#define _PFN_BITS (MAX_PHYSMEM_BITS - PAGE_SHIFT)
-#define OBJ_INDEX_BITS (BITS_PER_LONG - _PFN_BITS)
-#define OBJ_INDEX_MASK ((_AC(1, UL) << OBJ_INDEX_BITS) - 1)
-
-#define MAX(a, b) ((a) >= (b) ? (a) : (b))
-/* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */
-#define ZS_MIN_ALLOC_SIZE \
- MAX(32, (ZS_MAX_PAGES_PER_ZSPAGE << PAGE_SHIFT >> OBJ_INDEX_BITS))
-#define ZS_MAX_ALLOC_SIZE PAGE_SIZE
-
-/*
- * On systems with 4K page size, this gives 254 size classes! There is a
- * trader-off here:
- * - Large number of size classes is potentially wasteful as free page are
- * spread across these classes
- * - Small number of size classes causes large internal fragmentation
- * - Probably its better to use specific size classes (empirically
- * determined). NOTE: all those class sizes must be set as multiple of
- * ZS_ALIGN to make sure link_free itself never has to span 2 pages.
- *
- * ZS_MIN_ALLOC_SIZE and ZS_SIZE_CLASS_DELTA must be multiple of ZS_ALIGN
- * (reason above)
- */
-#define ZS_SIZE_CLASS_DELTA 16
-#define ZS_SIZE_CLASSES ((ZS_MAX_ALLOC_SIZE - ZS_MIN_ALLOC_SIZE) / \
- ZS_SIZE_CLASS_DELTA + 1)
-
-/*
- * We do not maintain any list for completely empty or full pages
- */
-enum fullness_group {
- ZS_ALMOST_FULL,
- ZS_ALMOST_EMPTY,
- _ZS_NR_FULLNESS_GROUPS,
-
- ZS_EMPTY,
- ZS_FULL
-};
-
-/*
- * We assign a page to ZS_ALMOST_EMPTY fullness group when:
- * n <= N / f, where
- * n = number of allocated objects
- * N = total number of objects zspage can store
- * f = 1/fullness_threshold_frac
- *
- * Similarly, we assign zspage to:
- * ZS_ALMOST_FULL when n > N / f
- * ZS_EMPTY when n == 0
- * ZS_FULL when n == N
- *
- * (see: fix_fullness_group())
- */
-static const int fullness_threshold_frac = 4;
-
-struct mapping_area {
- char *vm_buf; /* copy buffer for objects that span pages */
- char *vm_addr; /* address of kmap_atomic()'ed pages */
- enum zs_mapmode vm_mm; /* mapping mode */
-};
-
-struct size_class {
- /*
- * Size of objects stored in this class. Must be multiple
- * of ZS_ALIGN.
- */
- int size;
- unsigned int index;
-
- /* Number of PAGE_SIZE sized pages to combine to form a 'zspage' */
- int pages_per_zspage;
-
- spinlock_t lock;
-
- /* stats */
- u64 pages_allocated;
-
- struct page *fullness_list[_ZS_NR_FULLNESS_GROUPS];
-};
-
-/*
- * Placed within free objects to form a singly linked list.
- * For every zspage, first_page->freelist gives head of this list.
- *
- * This must be power of 2 and less than or equal to ZS_ALIGN
- */
-struct link_free {
- /* Handle of next free chunk (encodes <PFN, obj_idx>) */
- void *next;
-};
-
-struct zs_pool {
- struct size_class size_class[ZS_SIZE_CLASSES];
-
- gfp_t flags; /* allocation flags used when growing pool */
- const char *name;
-};
-
-#endif