diff options
Diffstat (limited to 'drivers/staging')
164 files changed, 585 insertions, 45296 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 075e775d3868..2f92cd698bef 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -48,6 +48,4 @@ source "drivers/staging/axis-fifo/Kconfig" source "drivers/staging/vme_user/Kconfig" -source "drivers/staging/gpib/Kconfig" - endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index e681e403509c..f5b8876aa536 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -13,4 +13,3 @@ obj-$(CONFIG_MOST) += most/ obj-$(CONFIG_GREYBUS) += greybus/ obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/ -obj-$(CONFIG_GPIB) += gpib/ diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c index 811bfdc578d8..509d620d6ce7 100644 --- a/drivers/staging/axis-fifo/axis-fifo.c +++ b/drivers/staging/axis-fifo/axis-fifo.c @@ -88,16 +88,8 @@ #define XLLF_INT_TC_MASK 0x08000000 /* Transmit complete */ #define XLLF_INT_RC_MASK 0x04000000 /* Receive complete */ #define XLLF_INT_TSE_MASK 0x02000000 /* Transmit length mismatch */ -#define XLLF_INT_TRC_MASK 0x01000000 /* Transmit reset complete */ -#define XLLF_INT_RRC_MASK 0x00800000 /* Receive reset complete */ -#define XLLF_INT_TFPF_MASK 0x00400000 /* Tx FIFO Programmable Full */ -#define XLLF_INT_TFPE_MASK 0x00200000 /* Tx FIFO Programmable Empty */ -#define XLLF_INT_RFPF_MASK 0x00100000 /* Rx FIFO Programmable Full */ -#define XLLF_INT_RFPE_MASK 0x00080000 /* Rx FIFO Programmable Empty */ -#define XLLF_INT_ALL_MASK 0xfff80000 /* All the ints */ -#define XLLF_INT_ERROR_MASK 0xf2000000 /* Error status ints */ -#define XLLF_INT_RXERROR_MASK 0xe0000000 /* Receive Error status ints */ -#define XLLF_INT_TXERROR_MASK 0x12000000 /* Transmit Error status ints */ + +#define XLLF_INT_CLEAR_ALL GENMASK(31, 0) /* ---------------------------- * globals @@ -125,7 +117,6 @@ MODULE_PARM_DESC(write_timeout, "ms to wait before blocking write() timing out; struct axis_fifo { int id; - int irq; /* interrupt */ void __iomem *base_addr; /* kernel space memory */ unsigned int rx_fifo_depth; /* max words in the receive fifo */ @@ -137,8 +128,6 @@ struct axis_fifo { struct mutex read_lock; /* lock for reading */ wait_queue_head_t write_queue; /* wait queue for asynchronos write */ struct mutex write_lock; /* lock for writing */ - unsigned int write_flags; /* write file flags */ - unsigned int read_flags; /* read file flags */ struct device *dt_device; /* device created from the device tree */ struct miscdevice miscdev; @@ -165,7 +154,7 @@ static void reset_ip_core(struct axis_fifo *fifo) XLLF_INT_RPORE_MASK | XLLF_INT_RPUE_MASK | XLLF_INT_TPOE_MASK | XLLF_INT_TSE_MASK, fifo->base_addr + XLLF_IER_OFFSET); - iowrite32(XLLF_INT_ALL_MASK, fifo->base_addr + XLLF_ISR_OFFSET); + iowrite32(XLLF_INT_CLEAR_ALL, fifo->base_addr + XLLF_ISR_OFFSET); } /** @@ -195,7 +184,7 @@ static ssize_t axis_fifo_read(struct file *f, char __user *buf, int ret; u32 tmp_buf[READ_BUF_SIZE]; - if (fifo->read_flags & O_NONBLOCK) { + if (f->f_flags & O_NONBLOCK) { /* * Device opened in non-blocking mode. Try to lock it and then * check if any packet is available. @@ -337,7 +326,7 @@ static ssize_t axis_fifo_write(struct file *f, const char __user *buf, if (words_to_write > (fifo->tx_fifo_depth - 4)) return -EINVAL; - if (fifo->write_flags & O_NONBLOCK) { + if (f->f_flags & O_NONBLOCK) { /* * Device opened in non-blocking mode. Try to lock it and then * check if there is any room to write the given buffer. @@ -396,106 +385,36 @@ end_unlock: static irqreturn_t axis_fifo_irq(int irq, void *dw) { - struct axis_fifo *fifo = (struct axis_fifo *)dw; - unsigned int pending_interrupts; - - do { - pending_interrupts = ioread32(fifo->base_addr + - XLLF_IER_OFFSET) & - ioread32(fifo->base_addr - + XLLF_ISR_OFFSET); - if (pending_interrupts & XLLF_INT_RC_MASK) { - /* packet received */ - - /* wake the reader process if it is waiting */ - wake_up(&fifo->read_queue); - - /* clear interrupt */ - iowrite32(XLLF_INT_RC_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts & XLLF_INT_TC_MASK) { - /* packet sent */ - - /* wake the writer process if it is waiting */ - wake_up(&fifo->write_queue); - - iowrite32(XLLF_INT_TC_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts & XLLF_INT_TFPF_MASK) { - /* transmit fifo programmable full */ - - iowrite32(XLLF_INT_TFPF_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts & XLLF_INT_TFPE_MASK) { - /* transmit fifo programmable empty */ - - iowrite32(XLLF_INT_TFPE_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts & XLLF_INT_RFPF_MASK) { - /* receive fifo programmable full */ - - iowrite32(XLLF_INT_RFPF_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts & XLLF_INT_RFPE_MASK) { - /* receive fifo programmable empty */ - - iowrite32(XLLF_INT_RFPE_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts & XLLF_INT_TRC_MASK) { - /* transmit reset complete interrupt */ - - iowrite32(XLLF_INT_TRC_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts & XLLF_INT_RRC_MASK) { - /* receive reset complete interrupt */ - - iowrite32(XLLF_INT_RRC_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts & XLLF_INT_RPURE_MASK) { - /* receive fifo under-read error interrupt */ - dev_err(fifo->dt_device, - "receive under-read interrupt\n"); - - iowrite32(XLLF_INT_RPURE_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts & XLLF_INT_RPORE_MASK) { - /* receive over-read error interrupt */ - dev_err(fifo->dt_device, - "receive over-read interrupt\n"); - - iowrite32(XLLF_INT_RPORE_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts & XLLF_INT_RPUE_MASK) { - /* receive underrun error interrupt */ - dev_err(fifo->dt_device, - "receive underrun error interrupt\n"); - - iowrite32(XLLF_INT_RPUE_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts & XLLF_INT_TPOE_MASK) { - /* transmit overrun error interrupt */ - dev_err(fifo->dt_device, - "transmit overrun error interrupt\n"); - - iowrite32(XLLF_INT_TPOE_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts & XLLF_INT_TSE_MASK) { - /* transmit length mismatch error interrupt */ - dev_err(fifo->dt_device, - "transmit length mismatch error interrupt\n"); - - iowrite32(XLLF_INT_TSE_MASK & XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } else if (pending_interrupts) { - /* unknown interrupt type */ - dev_err(fifo->dt_device, - "unknown interrupt(s) 0x%x\n", - pending_interrupts); - - iowrite32(XLLF_INT_ALL_MASK, - fifo->base_addr + XLLF_ISR_OFFSET); - } - } while (pending_interrupts); + struct axis_fifo *fifo = dw; + u32 isr, ier, intr; + + ier = ioread32(fifo->base_addr + XLLF_IER_OFFSET); + isr = ioread32(fifo->base_addr + XLLF_ISR_OFFSET); + intr = ier & isr; + + if (intr & XLLF_INT_RC_MASK) + wake_up(&fifo->read_queue); + + if (intr & XLLF_INT_TC_MASK) + wake_up(&fifo->write_queue); + + if (intr & XLLF_INT_RPURE_MASK) + dev_err(fifo->dt_device, "receive under-read interrupt\n"); + + if (intr & XLLF_INT_RPORE_MASK) + dev_err(fifo->dt_device, "receive over-read interrupt\n"); + + if (intr & XLLF_INT_RPUE_MASK) + dev_err(fifo->dt_device, "receive underrun error interrupt\n"); + + if (intr & XLLF_INT_TPOE_MASK) + dev_err(fifo->dt_device, "transmit overrun error interrupt\n"); + + if (intr & XLLF_INT_TSE_MASK) + dev_err(fifo->dt_device, + "transmit length mismatch error interrupt\n"); + + iowrite32(XLLF_INT_CLEAR_ALL, fifo->base_addr + XLLF_ISR_OFFSET); return IRQ_HANDLED; } @@ -504,27 +423,15 @@ static int axis_fifo_open(struct inode *inod, struct file *f) { struct axis_fifo *fifo = container_of(f->private_data, struct axis_fifo, miscdev); + unsigned int flags = f->f_flags & O_ACCMODE; + f->private_data = fifo; - if (((f->f_flags & O_ACCMODE) == O_WRONLY) || - ((f->f_flags & O_ACCMODE) == O_RDWR)) { - if (fifo->has_tx_fifo) { - fifo->write_flags = f->f_flags; - } else { - dev_err(fifo->dt_device, "tried to open device for write but the transmit fifo is disabled\n"); - return -EPERM; - } - } + if ((flags == O_WRONLY || flags == O_RDWR) && !fifo->has_tx_fifo) + return -EPERM; - if (((f->f_flags & O_ACCMODE) == O_RDONLY) || - ((f->f_flags & O_ACCMODE) == O_RDWR)) { - if (fifo->has_rx_fifo) { - fifo->read_flags = f->f_flags; - } else { - dev_err(fifo->dt_device, "tried to open device for read but the receive fifo is disabled\n"); - return -EPERM; - } - } + if ((flags == O_RDONLY || flags == O_RDWR) && !fifo->has_rx_fifo) + return -EPERM; return 0; } @@ -575,30 +482,14 @@ static void axis_fifo_debugfs_init(struct axis_fifo *fifo) &axis_fifo_debugfs_regs_fops); } -/* read named property from the device tree */ -static int get_dts_property(struct axis_fifo *fifo, - char *name, unsigned int *var) -{ - int rc; - - rc = of_property_read_u32(fifo->dt_device->of_node, name, var); - if (rc) { - dev_err(fifo->dt_device, "couldn't read IP dts property '%s'", - name); - return rc; - } - dev_dbg(fifo->dt_device, "dts property '%s' = %u\n", - name, *var); - - return 0; -} - static int axis_fifo_parse_dt(struct axis_fifo *fifo) { int ret; unsigned int value; + struct device_node *node = fifo->dt_device->of_node; - ret = get_dts_property(fifo, "xlnx,axi-str-rxd-tdata-width", &value); + ret = of_property_read_u32(node, "xlnx,axi-str-rxd-tdata-width", + &value); if (ret) { dev_err(fifo->dt_device, "missing xlnx,axi-str-rxd-tdata-width property\n"); goto end; @@ -608,7 +499,8 @@ static int axis_fifo_parse_dt(struct axis_fifo *fifo) goto end; } - ret = get_dts_property(fifo, "xlnx,axi-str-txd-tdata-width", &value); + ret = of_property_read_u32(node, "xlnx,axi-str-txd-tdata-width", + &value); if (ret) { dev_err(fifo->dt_device, "missing xlnx,axi-str-txd-tdata-width property\n"); goto end; @@ -618,30 +510,32 @@ static int axis_fifo_parse_dt(struct axis_fifo *fifo) goto end; } - ret = get_dts_property(fifo, "xlnx,rx-fifo-depth", - &fifo->rx_fifo_depth); + ret = of_property_read_u32(node, "xlnx,rx-fifo-depth", + &fifo->rx_fifo_depth); if (ret) { dev_err(fifo->dt_device, "missing xlnx,rx-fifo-depth property\n"); ret = -EIO; goto end; } - ret = get_dts_property(fifo, "xlnx,tx-fifo-depth", - &fifo->tx_fifo_depth); + ret = of_property_read_u32(node, "xlnx,tx-fifo-depth", + &fifo->tx_fifo_depth); if (ret) { dev_err(fifo->dt_device, "missing xlnx,tx-fifo-depth property\n"); ret = -EIO; goto end; } - ret = get_dts_property(fifo, "xlnx,use-rx-data", &fifo->has_rx_fifo); + ret = of_property_read_u32(node, "xlnx,use-rx-data", + &fifo->has_rx_fifo); if (ret) { dev_err(fifo->dt_device, "missing xlnx,use-rx-data property\n"); ret = -EIO; goto end; } - ret = get_dts_property(fifo, "xlnx,use-tx-data", &fifo->has_tx_fifo); + ret = of_property_read_u32(node, "xlnx,use-tx-data", + &fifo->has_tx_fifo); if (ret) { dev_err(fifo->dt_device, "missing xlnx,use-tx-data property\n"); ret = -EIO; @@ -659,6 +553,7 @@ static int axis_fifo_probe(struct platform_device *pdev) struct axis_fifo *fifo = NULL; char *device_name; int rc = 0; /* error return value */ + int irq; /* ---------------------------- * init wrapper device @@ -693,8 +588,6 @@ static int axis_fifo_probe(struct platform_device *pdev) if (IS_ERR(fifo->base_addr)) return PTR_ERR(fifo->base_addr); - dev_dbg(fifo->dt_device, "remapped memory to 0x%p\n", fifo->base_addr); - /* ---------------------------- * init IP * ---------------------------- @@ -712,17 +605,16 @@ static int axis_fifo_probe(struct platform_device *pdev) */ /* get IRQ resource */ - rc = platform_get_irq(pdev, 0); - if (rc < 0) - return rc; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; /* request IRQ */ - fifo->irq = rc; - rc = devm_request_irq(fifo->dt_device, fifo->irq, &axis_fifo_irq, 0, + rc = devm_request_irq(fifo->dt_device, irq, &axis_fifo_irq, 0, DRIVER_NAME, fifo); if (rc) { dev_err(fifo->dt_device, "couldn't allocate interrupt %i\n", - fifo->irq); + irq); return rc; } @@ -764,6 +656,8 @@ static void axis_fifo_remove(struct platform_device *pdev) static const struct of_device_id axis_fifo_of_match[] = { { .compatible = "xlnx,axi-fifo-mm-s-4.1", }, + { .compatible = "xlnx,axi-fifo-mm-s-4.2", }, + { .compatible = "xlnx,axi-fifo-mm-s-4.3", }, {}, }; MODULE_DEVICE_TABLE(of, axis_fifo_of_match); @@ -806,4 +700,4 @@ module_exit(axis_fifo_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jacob Feder <jacobsfeder@gmail.com>"); -MODULE_DESCRIPTION("Xilinx AXI-Stream FIFO v4.1 IP core driver"); +MODULE_DESCRIPTION("Xilinx AXI-Stream FIFO IP core driver"); diff --git a/drivers/staging/axis-fifo/axis-fifo.txt b/drivers/staging/axis-fifo/axis-fifo.txt index 5828e1b8e822..413b81a53202 100644 --- a/drivers/staging/axis-fifo/axis-fifo.txt +++ b/drivers/staging/axis-fifo/axis-fifo.txt @@ -14,7 +14,10 @@ AXI4-Lite interface. DOES NOT support: - AXI4 (non-lite) Required properties: -- compatible: Should be "xlnx,axi-fifo-mm-s-4.1" +- compatible: Should be one of: + "xlnx,axi-fifo-mm-s-4.1" + "xlnx,axi-fifo-mm-s-4.2" + "xlnx,axi-fifo-mm-s-4.3" - interrupt-names: Should be "interrupt" - interrupt-parent: Should be <&intc> - interrupts: Should contain interrupts lines. diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index 9e7b84071174..8a5ccc8ae0a1 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -1171,8 +1171,8 @@ int fbtft_probe_common(struct fbtft_display *display, par->pdev = pdev; if (display->buswidth == 0) { - dev_err(dev, "buswidth is not set\n"); - return -EINVAL; + ret = dev_err_probe(dev, -EINVAL, "buswidth is not set\n"); + goto out_release; } /* write register functions */ diff --git a/drivers/staging/gpib/Kconfig b/drivers/staging/gpib/Kconfig deleted file mode 100644 index aa01538d5beb..000000000000 --- a/drivers/staging/gpib/Kconfig +++ /dev/null @@ -1,255 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -menuconfig GPIB - tristate "Linux GPIB drivers" - help - Enable support for GPIB cards and dongles for Linux. GPIB - is the General Purpose Interface Bus which conforms to the - IEEE488 standard. - - This set of drivers can be used with the corresponding user - space library that can be found on Sourceforge under linux-gpib. - Select the drivers for your hardware from the list. - -if GPIB - -config GPIB_COMMON - tristate "GPIB core" - help - - Core common driver for all GPIB drivers. It provides the - interface for the userland library - - To compile this driver as a module, choose M here: the module will be - called gpib_common - -config GPIB_AGILENT_82350B - tristate "Agilent 8235xx PCI(e) adapters" - depends on PCI - select GPIB_COMMON - select GPIB_TMS9914 - help - Enable support for HP/Agilent/Keysight boards - 82350A - 82350B - 82351A - - To compile this driver as a module, choose M here: the module will be - called agilent_82350b. - -config GPIB_AGILENT_82357A - tristate "Agilent 82357a/b USB dongles" - select GPIB_COMMON - depends on USB - help - Enable support for Agilent/Keysight 82357x USB dongles. - - To compile this driver as a module, choose M here: the module will be - called agilent_82357a. - -config GPIB_CEC_PCI - tristate "CEC PCI board" - depends on PCI - depends on HAS_IOPORT - select GPIB_COMMON - select GPIB_NEC7210 - help - Enable support for Capital Equipment Corporation PCI-488 - and Keithly KPCI-488 boards. - - To compile this driver as a module, choose M here: the module will be - called cec_gpib. - -config GPIB_NI_PCI_ISA - tristate "NI PCI/ISA compatible boards" - depends on ISA_BUS || PCI || PCMCIA - depends on HAS_IOPORT - depends on PCMCIA || !PCMCIA - depends on HAS_IOPORT_MAP - select GPIB_COMMON - select GPIB_NEC7210 - help - Enable support for National Instruments boards based - on TNT4882 chips: - AT-GPIB (with NAT4882 chip) - AT-GPIB (with NEC7210 chip) - AT-GPIB/TNT - PCI-GPIB - PCIe-GPIB - PCI-GPIB+ - PCM-GPIB - PXI-GPIB - PCMCIA-GPIB - and Capital Equipment Corporation CEC-488 board. - - To compile this driver as a module, choose M here: the module will be - called tnt4882. - -config GPIB_CB7210 - tristate "Measurement Computing compatible boards" - depends on HAS_IOPORT - depends on ISA_BUS || PCI || PCMCIA - depends on PCMCIA || !PCMCIA - select GPIB_COMMON - select GPIB_NEC7210 - help - Enable support for Measurement Computing (Computer Boards): - CPCI_GPIB, ISA-GPIB, ISA-GPIB/LC, PCI-GPIB/1M, PCI-GPIB/300K and - PCMCIA-GPIB - Quancom PCIGPIB-1 with MC cb7210 chip - - To compile this driver as a module, choose M here: the module will be - -config GPIB_NI_USB - tristate "NI USB dongles" - select GPIB_COMMON - depends on USB - help - Enable support for National Instruments - GPIB-USB-B - GPIB-USB-HS - GPIB-USB-HS+ - Keithly - KUSB-488 - KUSB-488A - Measurement Computing (Computer Boards) - USB-488 - - To compile this driver as a module, choose M here: the module will be - called ni_usb. - -config GPIB_FLUKE - tristate "Fluke" - depends on OF - select GPIB_COMMON - select GPIB_NEC7210 - help - GPIB driver for Fluke based cda devices. - - To compile this driver as a module, choose M here: the module will be - called fluke_gpib - -config GPIB_FMH - tristate "FMH FPGA based devices" - select GPIB_COMMON - select GPIB_NEC7210 - depends on !PPC - depends on OF && PCI - help - GPIB driver for fmhess FPGA based devices - - To compile this driver as a module, choose M here: the module will be - called fmh_gpib - -config GPIB_GPIO - tristate "RPi GPIO bitbang" - depends on ARCH_BCM2835 || COMPILE_TEST - select GPIB_COMMON - help - GPIB bitbang driver Raspberry Pi GPIO adapters - - To compile this driver as a module, choose M here: the module will be - called gpib_bitbang - -config GPIB_HP82335 - tristate "HP82335/HP27209" - depends on ISA_BUS - select GPIB_COMMON - select GPIB_TMS9914 - help - GPIB driver for HP82335 and HP27209 boards - - To compile this driver as a module, choose M here: the module will be - called hp82335 - - -config GPIB_HP82341 - tristate "HP82341x" - select GPIB_COMMON - select GPIB_TMS9914 - depends on ISA_BUS || EISA - help - GPIB driver for HP82341 A/B/C/D boards - - To compile this driver as a module, choose M here: the module will be - called hp82341 - -config GPIB_INES - tristate "INES" - depends on PCI || ISA_BUS || PCMCIA - depends on PCMCIA || !PCMCIA - depends on HAS_IOPORT - select GPIB_COMMON - select GPIB_NEC7210 - help - GPIB driver for Ines compatible boards - Ines - GPIB-HS-NT - GPIB for Compact PCI - GPIB for PCI - GPIB for PCMCIA - GPIB PC/104 - Hameg - HO80-2 - Quancom - PCIGPIB-1 based on Ines iGPIB 72010 chip - - To compile this driver as a module, choose M here: the module will be - called ines_gpib - called cb7210. - -config GPIB_PCMCIA - def_bool y - depends on PCMCIA && (GPIB_NI_PCI_ISA || GPIB_CB7210 || GPIB_INES) - help - Enable PCMCIA/CArdbus support for National Instruments, - measurement computing boards and Ines boards. - -config GPIB_LPVO - tristate "LPVO DIY USB GPIB" - select GPIB_COMMON - depends on USB - help - Enable support for LPVO Self-made usb-gpib adapter - - To compile this driver as a module, choose M here: the module will be - called lpvo_usb_gpib - -config GPIB_PC2 - tristate "PC2 PC2a" - depends on ISA_BUS - depends on HAS_IOPORT - select GPIB_COMMON - select GPIB_NEC7210 - help - Enable support for pc2 and pc2a compatible adapters - Capital Equipment Corporation PC-488 - CONTEC GP-IB(PC) - Hameg HO80 - Iotech GP488B - Keithly MBC-488 - Measurement Computing ISA-GPIB-PCA2 - National Instruments PCII, PCIIa and PCII/IIa - - To compile this driver as a module, choose M here: the module will be - called pc2_gpib - - -config GPIB_TMS9914 - tristate - select GPIB_COMMON - help - Enable support for TMS 9914 chip. - - To compile this driver as a module, choose M here: the module will be - called tms9914 - -config GPIB_NEC7210 - tristate - select GPIB_COMMON - help - Enable support for NEC 7210 compatible chips. - - To compile this driver as a module, choose M here: the module will be - called nec7210 - -endif # GPIB diff --git a/drivers/staging/gpib/Makefile b/drivers/staging/gpib/Makefile deleted file mode 100644 index d0e88f5c0844..000000000000 --- a/drivers/staging/gpib/Makefile +++ /dev/null @@ -1,20 +0,0 @@ - -subdir-ccflags-y += -I$(src)/include -I$(src)/uapi - -obj-$(CONFIG_GPIB_AGILENT_82350B) += agilent_82350b/ -obj-$(CONFIG_GPIB_AGILENT_82357A) += agilent_82357a/ -obj-$(CONFIG_GPIB_CB7210) += cb7210/ -obj-$(CONFIG_GPIB_CEC_PCI) += cec/ -obj-$(CONFIG_GPIB_COMMON) += common/ -obj-$(CONFIG_GPIB_FLUKE) += eastwood/ -obj-$(CONFIG_GPIB_FMH) += fmh_gpib/ -obj-$(CONFIG_GPIB_GPIO) += gpio/ -obj-$(CONFIG_GPIB_HP82335) += hp_82335/ -obj-$(CONFIG_GPIB_HP82341) += hp_82341/ -obj-$(CONFIG_GPIB_INES) += ines/ -obj-$(CONFIG_GPIB_LPVO) += lpvo_usb_gpib/ -obj-$(CONFIG_GPIB_NEC7210) += nec7210/ -obj-$(CONFIG_GPIB_NI_USB) += ni_usb/ -obj-$(CONFIG_GPIB_PC2) += pc2/ -obj-$(CONFIG_GPIB_TMS9914) += tms9914/ -obj-$(CONFIG_GPIB_NI_PCI_ISA) += tnt4882/ diff --git a/drivers/staging/gpib/TODO b/drivers/staging/gpib/TODO deleted file mode 100644 index ab41a7f9ca5b..000000000000 --- a/drivers/staging/gpib/TODO +++ /dev/null @@ -1,24 +0,0 @@ -TODO: -- checkpatch.pl fixes - These checks should be ignored: - CHECK:ALLOC_SIZEOF_STRUCT: Prefer kmalloc(sizeof(*board->private_data)...) over kmalloc(sizeof(struct xxx_priv)...) - ./gpio/gpib_bitbang.c:50: ERROR:COMPLEX_MACRO: Macros with complex values should be enclosed in parenthese - This warning will be addressed later: WARNING:UNDOCUMENTED_DT_STRING: DT compatible string -- tidy-up comments: - - there are some "//comments" and "// comments" scattered around - - sometimes they are misaligned - - sometimes "// comments" are interleaved with "/* comments */" - - multiline comments should start with initial almost-blank line: - /* - * Good - * multiline - * comment - */ - /* Bad - * multiline - * comment - */ -- resolve XXX notes where possible -- fix FIXME notes -- clean-up commented-out code -- fix typos diff --git a/drivers/staging/gpib/agilent_82350b/Makefile b/drivers/staging/gpib/agilent_82350b/Makefile deleted file mode 100644 index f24e1e713a63..000000000000 --- a/drivers/staging/gpib/agilent_82350b/Makefile +++ /dev/null @@ -1,2 +0,0 @@ - -obj-$(CONFIG_GPIB_AGILENT_82350B) += agilent_82350b.o diff --git a/drivers/staging/gpib/agilent_82350b/agilent_82350b.c b/drivers/staging/gpib/agilent_82350b/agilent_82350b.c deleted file mode 100644 index 01a5bb43cd2d..000000000000 --- a/drivers/staging/gpib/agilent_82350b/agilent_82350b.c +++ /dev/null @@ -1,896 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * copyright : (C) 2002, 2004 by Frank Mori Hess * - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define DRV_NAME KBUILD_MODNAME - -#include "agilent_82350b.h" -#include <linux/delay.h> -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <asm/dma.h> -#include <linux/pci.h> -#include <linux/pci_ids.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/wait.h> - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB driver for Agilent 82350b"); - -static int read_transfer_counter(struct agilent_82350b_priv *a_priv); -static unsigned short read_and_clear_event_status(struct gpib_board *board); -static void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count); -static int agilent_82350b_write(struct gpib_board *board, u8 *buffer, - size_t length, int send_eoi, size_t *bytes_written); - -static int agilent_82350b_accel_read(struct gpib_board *board, u8 *buffer, - size_t length, int *end, size_t *bytes_read) - -{ - struct agilent_82350b_priv *a_priv = board->private_data; - struct tms9914_priv *tms_priv = &a_priv->tms9914_priv; - int retval = 0; - unsigned short event_status; - int i, num_fifo_bytes; - /* hardware doesn't support checking for end-of-string character when using fifo */ - if (tms_priv->eos_flags & REOS) - return tms9914_read(board, tms_priv, buffer, length, end, bytes_read); - - clear_bit(DEV_CLEAR_BN, &tms_priv->state); - - read_and_clear_event_status(board); - *end = 0; - *bytes_read = 0; - if (length == 0) - return 0; - /* disable fifo for the moment */ - writeb(DIRECTION_GPIB_TO_HOST, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); - /* handle corner case of board not in holdoff and one byte might slip in early */ - if (tms_priv->holdoff_active == 0 && length > 1) { - size_t num_bytes; - - retval = tms9914_read(board, tms_priv, buffer, 1, end, &num_bytes); - *bytes_read += num_bytes; - if (retval < 0 || *end) - return retval; - ++buffer; - --length; - } - tms9914_set_holdoff_mode(tms_priv, TMS9914_HOLDOFF_EOI); - tms9914_release_holdoff(tms_priv); - i = 0; - num_fifo_bytes = length - 1; - /* disable BI interrupts */ - write_byte(tms_priv, tms_priv->imr0_bits & ~HR_BIIE, IMR0); - while (i < num_fifo_bytes && *end == 0) { - int block_size; - int j; - int count; - - block_size = min(num_fifo_bytes - i, agilent_82350b_fifo_size); - set_transfer_counter(a_priv, block_size); - writeb(ENABLE_TI_TO_SRAM | DIRECTION_GPIB_TO_HOST, - a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); - if (agilent_82350b_fifo_is_halted(a_priv)) - writeb(RESTART_STREAM_BIT, a_priv->gpib_base + STREAM_STATUS_REG); - - clear_bit(READ_READY_BN, &tms_priv->state); - - retval = wait_event_interruptible(board->wait, - ((event_status = - read_and_clear_event_status(board)) & - (TERM_COUNT_STATUS_BIT | - BUFFER_END_STATUS_BIT)) || - test_bit(DEV_CLEAR_BN, &tms_priv->state) || - test_bit(TIMO_NUM, &board->status)); - if (retval) { - retval = -ERESTARTSYS; - break; - } - count = block_size - read_transfer_counter(a_priv); - for (j = 0; j < count && i < num_fifo_bytes; ++j) - buffer[i++] = readb(a_priv->sram_base + j); - if (event_status & BUFFER_END_STATUS_BIT) { - clear_bit(RECEIVED_END_BN, &tms_priv->state); - - tms_priv->holdoff_active = 1; - *end = 1; - } - if (test_bit(TIMO_NUM, &board->status)) { - retval = -ETIMEDOUT; - break; - } - if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) { - retval = -EINTR; - break; - } - } - /* re-enable BI interrupts */ - write_byte(tms_priv, tms_priv->imr0_bits, IMR0); - *bytes_read += i; - buffer += i; - length -= i; - writeb(DIRECTION_GPIB_TO_HOST, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); - if (retval < 0) - return retval; - /* read last bytes if we havn't received an END yet */ - if (*end == 0) { - size_t num_bytes; - /* try to make sure we holdoff after last byte read */ - retval = tms9914_read(board, tms_priv, buffer, length, end, &num_bytes); - *bytes_read += num_bytes; - if (retval < 0) - return retval; - } - return 0; -} - -static int translate_wait_return_value(struct gpib_board *board, int retval) - -{ - struct agilent_82350b_priv *a_priv = board->private_data; - struct tms9914_priv *tms_priv = &a_priv->tms9914_priv; - - if (retval) - return -ERESTARTSYS; - if (test_bit(TIMO_NUM, &board->status)) - return -ETIMEDOUT; - if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) - return -EINTR; - return 0; -} - -static int agilent_82350b_accel_write(struct gpib_board *board, u8 *buffer, - size_t length, int send_eoi, - size_t *bytes_written) -{ - struct agilent_82350b_priv *a_priv = board->private_data; - struct tms9914_priv *tms_priv = &a_priv->tms9914_priv; - int i, j; - unsigned short event_status; - int retval = 0; - int fifotransferlength = length; - int block_size = 0; - size_t num_bytes; - - *bytes_written = 0; - if (send_eoi) - --fifotransferlength; - - clear_bit(DEV_CLEAR_BN, &tms_priv->state); - - writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); - - event_status = read_and_clear_event_status(board); - -#ifdef EXPERIMENTAL - /* wait for previous BO to complete if any */ - retval = wait_event_interruptible(board->wait, - test_bit(DEV_CLEAR_BN, &tms_priv->state) || - test_bit(WRITE_READY_BN, &tms_priv->state) || - test_bit(TIMO_NUM, &board->status)); - retval = translate_wait_return_value(board, retval); - - if (retval) - return retval; -#endif - - if (fifotransferlength > 0) { - retval = agilent_82350b_write(board, buffer, 1, 0, &num_bytes); - *bytes_written += num_bytes; - if (retval < 0) - return retval; - } - - write_byte(tms_priv, tms_priv->imr0_bits & ~HR_BOIE, IMR0); - for (i = 1; i < fifotransferlength;) { - clear_bit(WRITE_READY_BN, &tms_priv->state); - - block_size = min(fifotransferlength - i, agilent_82350b_fifo_size); - set_transfer_counter(a_priv, block_size); - for (j = 0; j < block_size; ++j, ++i) { - /* load data into board's sram */ - writeb(buffer[i], a_priv->sram_base + j); - } - writeb(ENABLE_TI_TO_SRAM, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); - - if (agilent_82350b_fifo_is_halted(a_priv)) - writeb(RESTART_STREAM_BIT, a_priv->gpib_base + STREAM_STATUS_REG); - - retval = wait_event_interruptible(board->wait, - ((event_status = - read_and_clear_event_status(board)) & - TERM_COUNT_STATUS_BIT) || - test_bit(DEV_CLEAR_BN, &tms_priv->state) || - test_bit(TIMO_NUM, &board->status)); - writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); - num_bytes = block_size - read_transfer_counter(a_priv); - - *bytes_written += num_bytes; - retval = translate_wait_return_value(board, retval); - if (retval) - break; - } - write_byte(tms_priv, tms_priv->imr0_bits, IMR0); - if (retval < 0) - return retval; - - if (send_eoi) { - retval = agilent_82350b_write(board, buffer + fifotransferlength, 1, send_eoi, - &num_bytes); - *bytes_written += num_bytes; - if (retval < 0) - return retval; - } - return 0; -} - -static unsigned short read_and_clear_event_status(struct gpib_board *board) -{ - struct agilent_82350b_priv *a_priv = board->private_data; - unsigned long flags; - unsigned short status; - - spin_lock_irqsave(&board->spinlock, flags); - status = a_priv->event_status_bits; - a_priv->event_status_bits = 0; - spin_unlock_irqrestore(&board->spinlock, flags); - return status; -} - -static irqreturn_t agilent_82350b_interrupt(int irq, void *arg) - -{ - int tms9914_status1 = 0, tms9914_status2 = 0; - int event_status; - struct gpib_board *board = arg; - struct agilent_82350b_priv *a_priv = board->private_data; - unsigned long flags; - irqreturn_t retval = IRQ_NONE; - - spin_lock_irqsave(&board->spinlock, flags); - event_status = readb(a_priv->gpib_base + EVENT_STATUS_REG); - if (event_status & IRQ_STATUS_BIT) - retval = IRQ_HANDLED; - - if (event_status & TMS9914_IRQ_STATUS_BIT) { - tms9914_status1 = read_byte(&a_priv->tms9914_priv, ISR0); - tms9914_status2 = read_byte(&a_priv->tms9914_priv, ISR1); - tms9914_interrupt_have_status(board, &a_priv->tms9914_priv, tms9914_status1, - tms9914_status2); - } - /* write-clear status bits */ - if (event_status & (BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT)) { - writeb(event_status & (BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT), - a_priv->gpib_base + EVENT_STATUS_REG); - a_priv->event_status_bits |= event_status; - wake_up_interruptible(&board->wait); - } - spin_unlock_irqrestore(&board->spinlock, flags); - return retval; -} - -static void agilent_82350b_detach(struct gpib_board *board); - -static int read_transfer_counter(struct agilent_82350b_priv *a_priv) -{ - int lo, mid, value; - - lo = readb(a_priv->gpib_base + XFER_COUNT_LO_REG); - mid = readb(a_priv->gpib_base + XFER_COUNT_MID_REG); - value = (lo & 0xff) | ((mid << 8) & 0x7f00); - value = ~(value - 1) & 0x7fff; - return value; -} - -static void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count) -{ - int complement = -count; - - writeb(complement & 0xff, a_priv->gpib_base + XFER_COUNT_LO_REG); - writeb((complement >> 8) & 0xff, a_priv->gpib_base + XFER_COUNT_MID_REG); - /* I don't think the hi count reg is even used, but oh well */ - writeb((complement >> 16) & 0xf, a_priv->gpib_base + XFER_COUNT_HI_REG); -} - -/* wrappers for interface functions */ -static int agilent_82350b_read(struct gpib_board *board, u8 *buffer, - size_t length, int *end, size_t *bytes_read) -{ - struct agilent_82350b_priv *priv = board->private_data; - - return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read); -} - -static int agilent_82350b_write(struct gpib_board *board, u8 *buffer, - size_t length, int send_eoi, size_t *bytes_written) - -{ - struct agilent_82350b_priv *priv = board->private_data; - - return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written); -} - -static int agilent_82350b_command(struct gpib_board *board, u8 *buffer, - size_t length, size_t *bytes_written) - -{ - struct agilent_82350b_priv *priv = board->private_data; - - return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written); -} - -static int agilent_82350b_take_control(struct gpib_board *board, int synchronous) - -{ - struct agilent_82350b_priv *priv = board->private_data; - - return tms9914_take_control_workaround(board, &priv->tms9914_priv, synchronous); -} - -static int agilent_82350b_go_to_standby(struct gpib_board *board) - -{ - struct agilent_82350b_priv *priv = board->private_data; - - return tms9914_go_to_standby(board, &priv->tms9914_priv); -} - -static int agilent_82350b_request_system_control(struct gpib_board *board, int request_control) -{ - struct agilent_82350b_priv *a_priv = board->private_data; - - if (request_control) { - a_priv->card_mode_bits |= CM_SYSTEM_CONTROLLER_BIT; - if (a_priv->model != MODEL_82350A) - writeb(IC_SYSTEM_CONTROLLER_BIT, a_priv->gpib_base + INTERNAL_CONFIG_REG); - } else { - a_priv->card_mode_bits &= ~CM_SYSTEM_CONTROLLER_BIT; - if (a_priv->model != MODEL_82350A) - writeb(0, a_priv->gpib_base + INTERNAL_CONFIG_REG); - } - writeb(a_priv->card_mode_bits, a_priv->gpib_base + CARD_MODE_REG); - return tms9914_request_system_control(board, &a_priv->tms9914_priv, request_control); -} - -static void agilent_82350b_interface_clear(struct gpib_board *board, int assert) - -{ - struct agilent_82350b_priv *priv = board->private_data; - - tms9914_interface_clear(board, &priv->tms9914_priv, assert); -} - -static void agilent_82350b_remote_enable(struct gpib_board *board, int enable) -{ - struct agilent_82350b_priv *priv = board->private_data; - - tms9914_remote_enable(board, &priv->tms9914_priv, enable); -} - -static int agilent_82350b_enable_eos(struct gpib_board *board, u8 eos_byte, - int compare_8_bits) -{ - struct agilent_82350b_priv *priv = board->private_data; - - return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits); -} - -static void agilent_82350b_disable_eos(struct gpib_board *board) -{ - struct agilent_82350b_priv *priv = board->private_data; - - tms9914_disable_eos(board, &priv->tms9914_priv); -} - -static unsigned int agilent_82350b_update_status(struct gpib_board *board, - unsigned int clear_mask) -{ - struct agilent_82350b_priv *priv = board->private_data; - - return tms9914_update_status(board, &priv->tms9914_priv, clear_mask); -} - -static int agilent_82350b_primary_address(struct gpib_board *board, - unsigned int address) -{ - struct agilent_82350b_priv *priv = board->private_data; - - return tms9914_primary_address(board, &priv->tms9914_priv, address); -} - -static int agilent_82350b_secondary_address(struct gpib_board *board, - unsigned int address, int enable) -{ - struct agilent_82350b_priv *priv = board->private_data; - - return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable); -} - -static int agilent_82350b_parallel_poll(struct gpib_board *board, u8 *result) -{ - struct agilent_82350b_priv *priv = board->private_data; - - return tms9914_parallel_poll(board, &priv->tms9914_priv, result); -} - -static void agilent_82350b_parallel_poll_configure(struct gpib_board *board, - u8 config) -{ - struct agilent_82350b_priv *priv = board->private_data; - - tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config); -} - -static void agilent_82350b_parallel_poll_response(struct gpib_board *board, int ist) -{ - struct agilent_82350b_priv *priv = board->private_data; - - tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist); -} - -static void agilent_82350b_serial_poll_response(struct gpib_board *board, u8 status) -{ - struct agilent_82350b_priv *priv = board->private_data; - - tms9914_serial_poll_response(board, &priv->tms9914_priv, status); -} - -static u8 agilent_82350b_serial_poll_status(struct gpib_board *board) -{ - struct agilent_82350b_priv *priv = board->private_data; - - return tms9914_serial_poll_status(board, &priv->tms9914_priv); -} - -static int agilent_82350b_line_status(const struct gpib_board *board) -{ - struct agilent_82350b_priv *priv = board->private_data; - - return tms9914_line_status(board, &priv->tms9914_priv); -} - -static int agilent_82350b_t1_delay(struct gpib_board *board, unsigned int nanosec) -{ - struct agilent_82350b_priv *a_priv = board->private_data; - static const int nanosec_per_clock = 30; - unsigned int value; - - tms9914_t1_delay(board, &a_priv->tms9914_priv, nanosec); - - value = (nanosec + nanosec_per_clock - 1) / nanosec_per_clock; - if (value > 0xff) - value = 0xff; - writeb(value, a_priv->gpib_base + T1_DELAY_REG); - return value * nanosec_per_clock; -} - -static void agilent_82350b_return_to_local(struct gpib_board *board) -{ - struct agilent_82350b_priv *priv = board->private_data; - - tms9914_return_to_local(board, &priv->tms9914_priv); -} - -static int agilent_82350b_allocate_private(struct gpib_board *board) -{ - board->private_data = kzalloc(sizeof(struct agilent_82350b_priv), GFP_KERNEL); - if (!board->private_data) - return -ENOMEM; - return 0; -} - -static void agilent_82350b_free_private(struct gpib_board *board) -{ - kfree(board->private_data); - board->private_data = NULL; -} - -static int init_82350a_hardware(struct gpib_board *board, - const struct gpib_board_config *config) -{ - struct agilent_82350b_priv *a_priv = board->private_data; - static const unsigned int firmware_length = 5302; - unsigned int borg_status; - static const unsigned int timeout = 1000; - int i, j; - const char *firmware_data = config->init_data; - const unsigned int plx_cntrl_static_bits = PLX9050_WAITO_NOT_USER0_SELECT_BIT | - PLX9050_USER0_OUTPUT_BIT | - PLX9050_LLOCK_NOT_USER1_SELECT_BIT | - PLX9050_USER1_OUTPUT_BIT | - PLX9050_USER2_OUTPUT_BIT | - PLX9050_USER3_OUTPUT_BIT | - PLX9050_PCI_READ_MODE_BIT | - PLX9050_PCI_WRITE_MODE_BIT | - PLX9050_PCI_RETRY_DELAY_BITS(64) | - PLX9050_DIRECT_SLAVE_LOCK_ENABLE_BIT; - - /* load borg data */ - borg_status = readb(a_priv->borg_base); - if ((borg_status & BORG_DONE_BIT)) - return 0; - /* need to programme borg */ - if (!config->init_data || config->init_data_length != firmware_length) { - dev_err(board->gpib_dev, "the 82350A board requires firmware after powering on.\n"); - return -EIO; - } - dev_dbg(board->gpib_dev, "Loading firmware...\n"); - - /* tickle the borg */ - writel(plx_cntrl_static_bits | PLX9050_USER3_DATA_BIT, - a_priv->plx_base + PLX9050_CNTRL_REG); - usleep_range(1000, 2000); - writel(plx_cntrl_static_bits, a_priv->plx_base + PLX9050_CNTRL_REG); - usleep_range(1000, 2000); - writel(plx_cntrl_static_bits | PLX9050_USER3_DATA_BIT, - a_priv->plx_base + PLX9050_CNTRL_REG); - usleep_range(1000, 2000); - - for (i = 0; i < config->init_data_length; ++i) { - for (j = 0; j < timeout && (readb(a_priv->borg_base) & BORG_READY_BIT) == 0; ++j) { - if (need_resched()) - schedule(); - usleep_range(10, 20); - } - if (j == timeout) { - dev_err(board->gpib_dev, "timed out loading firmware.\n"); - return -ETIMEDOUT; - } - writeb(firmware_data[i], a_priv->gpib_base + CONFIG_DATA_REG); - } - for (j = 0; j < timeout && (readb(a_priv->borg_base) & BORG_DONE_BIT) == 0; ++j) { - if (need_resched()) - schedule(); - usleep_range(10, 20); - } - if (j == timeout) { - dev_err(board->gpib_dev, "timed out waiting for firmware load to complete.\n"); - return -ETIMEDOUT; - } - dev_dbg(board->gpib_dev, " ...done.\n"); - return 0; -} - -static int test_sram(struct gpib_board *board) - -{ - struct agilent_82350b_priv *a_priv = board->private_data; - unsigned int i; - const unsigned int sram_length = pci_resource_len(a_priv->pci_device, SRAM_82350A_REGION); - /* test SRAM */ - const unsigned int byte_mask = 0xff; - - for (i = 0; i < sram_length; ++i) { - writeb(i & byte_mask, a_priv->sram_base + i); - if (need_resched()) - schedule(); - } - for (i = 0; i < sram_length; ++i) { - unsigned int read_value = readb(a_priv->sram_base + i); - - if ((i & byte_mask) != read_value) { - dev_err(board->gpib_dev, "SRAM test failed at %d wanted %d got %d\n", - i, (i & byte_mask), read_value); - return -EIO; - } - if (need_resched()) - schedule(); - } - dev_dbg(board->gpib_dev, "SRAM test passed 0x%x bytes checked\n", sram_length); - return 0; -} - -static int agilent_82350b_generic_attach(struct gpib_board *board, - const struct gpib_board_config *config, - int use_fifos) - -{ - struct agilent_82350b_priv *a_priv; - struct tms9914_priv *tms_priv; - int retval; - - board->status = 0; - - if (agilent_82350b_allocate_private(board)) - return -ENOMEM; - a_priv = board->private_data; - a_priv->using_fifos = use_fifos; - tms_priv = &a_priv->tms9914_priv; - tms_priv->read_byte = tms9914_iomem_read_byte; - tms_priv->write_byte = tms9914_iomem_write_byte; - tms_priv->offset = 1; - - /* find board */ - a_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_AGILENT, - PCI_DEVICE_ID_82350B, NULL); - if (a_priv->pci_device) { - a_priv->model = MODEL_82350B; - dev_dbg(board->gpib_dev, "Agilent 82350B board found\n"); - - } else { - a_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_AGILENT, - PCI_DEVICE_ID_82351A, NULL); - if (a_priv->pci_device) { - a_priv->model = MODEL_82351A; - dev_dbg(board->gpib_dev, "Agilent 82351B board found\n"); - - } else { - a_priv->pci_device = gpib_pci_get_subsys(config, PCI_VENDOR_ID_PLX, - PCI_DEVICE_ID_PLX_9050, - PCI_VENDOR_ID_HP, - PCI_SUBDEVICE_ID_82350A, - a_priv->pci_device); - if (a_priv->pci_device) { - a_priv->model = MODEL_82350A; - dev_dbg(board->gpib_dev, "HP/Agilent 82350A board found\n"); - } else { - dev_err(board->gpib_dev, "no 82350/82351 board found\n"); - return -ENODEV; - } - } - } - if (pci_enable_device(a_priv->pci_device)) { - dev_err(board->gpib_dev, "error enabling pci device\n"); - return -EIO; - } - if (pci_request_regions(a_priv->pci_device, DRV_NAME)) - return -ENOMEM; - switch (a_priv->model) { - case MODEL_82350A: - a_priv->plx_base = ioremap(pci_resource_start(a_priv->pci_device, PLX_MEM_REGION), - pci_resource_len(a_priv->pci_device, PLX_MEM_REGION)); - dev_dbg(board->gpib_dev, "plx base address remapped to 0x%p\n", a_priv->plx_base); - a_priv->gpib_base = ioremap(pci_resource_start(a_priv->pci_device, - GPIB_82350A_REGION), - pci_resource_len(a_priv->pci_device, - GPIB_82350A_REGION)); - dev_dbg(board->gpib_dev, "chip base address remapped to 0x%p\n", a_priv->gpib_base); - tms_priv->mmiobase = a_priv->gpib_base + TMS9914_BASE_REG; - a_priv->sram_base = ioremap(pci_resource_start(a_priv->pci_device, - SRAM_82350A_REGION), - pci_resource_len(a_priv->pci_device, - SRAM_82350A_REGION)); - dev_dbg(board->gpib_dev, "sram base address remapped to 0x%p\n", a_priv->sram_base); - a_priv->borg_base = ioremap(pci_resource_start(a_priv->pci_device, - BORG_82350A_REGION), - pci_resource_len(a_priv->pci_device, - BORG_82350A_REGION)); - dev_dbg(board->gpib_dev, "borg base address remapped to 0x%p\n", a_priv->borg_base); - - retval = init_82350a_hardware(board, config); - if (retval < 0) - return retval; - break; - case MODEL_82350B: - case MODEL_82351A: - a_priv->gpib_base = ioremap(pci_resource_start(a_priv->pci_device, GPIB_REGION), - pci_resource_len(a_priv->pci_device, GPIB_REGION)); - dev_dbg(board->gpib_dev, "chip base address remapped to 0x%p\n", a_priv->gpib_base); - tms_priv->mmiobase = a_priv->gpib_base + TMS9914_BASE_REG; - a_priv->sram_base = ioremap(pci_resource_start(a_priv->pci_device, SRAM_REGION), - pci_resource_len(a_priv->pci_device, SRAM_REGION)); - dev_dbg(board->gpib_dev, "sram base address remapped to 0x%p\n", a_priv->sram_base); - a_priv->misc_base = ioremap(pci_resource_start(a_priv->pci_device, MISC_REGION), - pci_resource_len(a_priv->pci_device, MISC_REGION)); - dev_dbg(board->gpib_dev, "misc base address remapped to 0x%p\n", a_priv->misc_base); - break; - default: - dev_err(board->gpib_dev, "invalid board\n"); - return -ENODEV; - } - - retval = test_sram(board); - if (retval < 0) - return retval; - - if (request_irq(a_priv->pci_device->irq, agilent_82350b_interrupt, - IRQF_SHARED, DRV_NAME, board)) { - dev_err(board->gpib_dev, "failed to obtain irq %d\n", a_priv->pci_device->irq); - return -EIO; - } - a_priv->irq = a_priv->pci_device->irq; - dev_dbg(board->gpib_dev, " IRQ %d\n", a_priv->irq); - - writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG); - a_priv->card_mode_bits = ENABLE_PCI_IRQ_BIT; - writeb(a_priv->card_mode_bits, a_priv->gpib_base + CARD_MODE_REG); - - if (a_priv->model == MODEL_82350A) { - /* enable PCI interrupts for 82350a */ - writel(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR2_POLARITY_BIT | - PLX9050_PCI_INTR_EN_BIT, - a_priv->plx_base + PLX9050_INTCSR_REG); - } - - if (use_fifos) { - writeb(ENABLE_BUFFER_END_EVENTS_BIT | ENABLE_TERM_COUNT_EVENTS_BIT, - a_priv->gpib_base + EVENT_ENABLE_REG); - writeb(ENABLE_TERM_COUNT_INTERRUPT_BIT | ENABLE_BUFFER_END_INTERRUPT_BIT | - ENABLE_TMS9914_INTERRUPTS_BIT, a_priv->gpib_base + INTERRUPT_ENABLE_REG); - /* write-clear event status bits */ - writeb(BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT, - a_priv->gpib_base + EVENT_STATUS_REG); - } else { - writeb(0, a_priv->gpib_base + EVENT_ENABLE_REG); - writeb(ENABLE_TMS9914_INTERRUPTS_BIT, - a_priv->gpib_base + INTERRUPT_ENABLE_REG); - } - board->t1_nano_sec = agilent_82350b_t1_delay(board, 2000); - tms9914_board_reset(tms_priv); - - tms9914_online(board, tms_priv); - - return 0; -} - -static int agilent_82350b_unaccel_attach(struct gpib_board *board, - const struct gpib_board_config *config) -{ - return agilent_82350b_generic_attach(board, config, 0); -} - -static int agilent_82350b_accel_attach(struct gpib_board *board, - const struct gpib_board_config *config) -{ - return agilent_82350b_generic_attach(board, config, 1); -} - -static void agilent_82350b_detach(struct gpib_board *board) -{ - struct agilent_82350b_priv *a_priv = board->private_data; - struct tms9914_priv *tms_priv; - - if (a_priv) { - if (a_priv->plx_base) /* disable interrupts */ - writel(0, a_priv->plx_base + PLX9050_INTCSR_REG); - - tms_priv = &a_priv->tms9914_priv; - if (a_priv->irq) - free_irq(a_priv->irq, board); - if (a_priv->gpib_base) { - tms9914_board_reset(tms_priv); - if (a_priv->misc_base) - iounmap(a_priv->misc_base); - if (a_priv->borg_base) - iounmap(a_priv->borg_base); - if (a_priv->sram_base) - iounmap(a_priv->sram_base); - if (a_priv->gpib_base) - iounmap(a_priv->gpib_base); - if (a_priv->plx_base) - iounmap(a_priv->plx_base); - pci_release_regions(a_priv->pci_device); - } - if (a_priv->pci_device) - pci_dev_put(a_priv->pci_device); - } - agilent_82350b_free_private(board); -} - -static struct gpib_interface agilent_82350b_unaccel_interface = { - .name = "agilent_82350b_unaccel", - .attach = agilent_82350b_unaccel_attach, - .detach = agilent_82350b_detach, - .read = agilent_82350b_read, - .write = agilent_82350b_write, - .command = agilent_82350b_command, - .request_system_control = agilent_82350b_request_system_control, - .take_control = agilent_82350b_take_control, - .go_to_standby = agilent_82350b_go_to_standby, - .interface_clear = agilent_82350b_interface_clear, - .remote_enable = agilent_82350b_remote_enable, - .enable_eos = agilent_82350b_enable_eos, - .disable_eos = agilent_82350b_disable_eos, - .parallel_poll = agilent_82350b_parallel_poll, - .parallel_poll_configure = agilent_82350b_parallel_poll_configure, - .parallel_poll_response = agilent_82350b_parallel_poll_response, - .local_parallel_poll_mode = NULL, /* XXX */ - .line_status = agilent_82350b_line_status, - .update_status = agilent_82350b_update_status, - .primary_address = agilent_82350b_primary_address, - .secondary_address = agilent_82350b_secondary_address, - .serial_poll_response = agilent_82350b_serial_poll_response, - .serial_poll_status = agilent_82350b_serial_poll_status, - .t1_delay = agilent_82350b_t1_delay, - .return_to_local = agilent_82350b_return_to_local, -}; - -static struct gpib_interface agilent_82350b_interface = { - .name = "agilent_82350b", - .attach = agilent_82350b_accel_attach, - .detach = agilent_82350b_detach, - .read = agilent_82350b_accel_read, - .write = agilent_82350b_accel_write, - .command = agilent_82350b_command, - .request_system_control = agilent_82350b_request_system_control, - .take_control = agilent_82350b_take_control, - .go_to_standby = agilent_82350b_go_to_standby, - .interface_clear = agilent_82350b_interface_clear, - .remote_enable = agilent_82350b_remote_enable, - .enable_eos = agilent_82350b_enable_eos, - .disable_eos = agilent_82350b_disable_eos, - .parallel_poll = agilent_82350b_parallel_poll, - .parallel_poll_configure = agilent_82350b_parallel_poll_configure, - .parallel_poll_response = agilent_82350b_parallel_poll_response, - .local_parallel_poll_mode = NULL, /* XXX */ - .line_status = agilent_82350b_line_status, - .update_status = agilent_82350b_update_status, - .primary_address = agilent_82350b_primary_address, - .secondary_address = agilent_82350b_secondary_address, - .serial_poll_response = agilent_82350b_serial_poll_response, - .serial_poll_status = agilent_82350b_serial_poll_status, - .t1_delay = agilent_82350b_t1_delay, - .return_to_local = agilent_82350b_return_to_local, -}; - -static int agilent_82350b_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) - -{ - return 0; -} - -static const struct pci_device_id agilent_82350b_pci_table[] = { - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_HP, - PCI_SUBDEVICE_ID_82350A, 0, 0, 0 }, - { PCI_VENDOR_ID_AGILENT, PCI_DEVICE_ID_82350B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_AGILENT, PCI_DEVICE_ID_82351A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, agilent_82350b_pci_table); - -static struct pci_driver agilent_82350b_pci_driver = { - .name = DRV_NAME, - .id_table = agilent_82350b_pci_table, - .probe = &agilent_82350b_pci_probe -}; - -static int __init agilent_82350b_init_module(void) -{ - int result; - - result = pci_register_driver(&agilent_82350b_pci_driver); - if (result) { - pr_err("pci_register_driver failed: error = %d\n", result); - return result; - } - - result = gpib_register_driver(&agilent_82350b_unaccel_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_unaccel; - } - - result = gpib_register_driver(&agilent_82350b_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_interface; - } - - return 0; - -err_interface: - gpib_unregister_driver(&agilent_82350b_unaccel_interface); -err_unaccel: - pci_unregister_driver(&agilent_82350b_pci_driver); - - return result; -} - -static void __exit agilent_82350b_exit_module(void) -{ - gpib_unregister_driver(&agilent_82350b_interface); - gpib_unregister_driver(&agilent_82350b_unaccel_interface); - - pci_unregister_driver(&agilent_82350b_pci_driver); -} - -module_init(agilent_82350b_init_module); -module_exit(agilent_82350b_exit_module); diff --git a/drivers/staging/gpib/agilent_82350b/agilent_82350b.h b/drivers/staging/gpib/agilent_82350b/agilent_82350b.h deleted file mode 100644 index ef841957297f..000000000000 --- a/drivers/staging/gpib/agilent_82350b/agilent_82350b.h +++ /dev/null @@ -1,157 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002, 2004 by Frank Mori Hess * - ***************************************************************************/ - -#include "gpibP.h" -#include "plx9050.h" -#include "tms9914.h" - -enum pci_vendor_ids { - PCI_VENDOR_ID_AGILENT = 0x15bc, -}; - -enum pci_device_ids { - PCI_DEVICE_ID_82350B = 0x0b01, - PCI_DEVICE_ID_82351A = 0x1218 -}; - -enum pci_subdevice_ids { - PCI_SUBDEVICE_ID_82350A = 0x10b0, -}; - -enum pci_regions_82350a { - PLX_MEM_REGION = 0, - PLX_IO_REGION = 1, - GPIB_82350A_REGION = 2, - SRAM_82350A_REGION = 3, - BORG_82350A_REGION = 4 -}; - -enum pci_regions_82350b { - GPIB_REGION = 0, - SRAM_REGION = 1, - MISC_REGION = 2, -}; - -enum board_model { - MODEL_82350A, - MODEL_82350B, - MODEL_82351A -}; - -/* struct which defines private_data for board */ -struct agilent_82350b_priv { - struct tms9914_priv tms9914_priv; - struct pci_dev *pci_device; - void __iomem *plx_base; /* 82350a only */ - void __iomem *gpib_base; - void __iomem *sram_base; - void __iomem *misc_base; - void __iomem *borg_base; - int irq; - unsigned short card_mode_bits; - unsigned short event_status_bits; - enum board_model model; - bool using_fifos; -}; - -/* registers */ -enum agilent_82350b_gpib_registers - -{ - CARD_MODE_REG = 0x1, - CONFIG_DATA_REG = 0x2, /* 82350A specific */ - INTERRUPT_ENABLE_REG = 0x3, - EVENT_STATUS_REG = 0x4, - EVENT_ENABLE_REG = 0x5, - STREAM_STATUS_REG = 0x7, - DEBUG_RAM0_REG = 0x8, - DEBUG_RAM1_REG = 0x9, - DEBUG_RAM2_REG = 0xa, - DEBUG_RAM3_REG = 0xb, - XFER_COUNT_LO_REG = 0xc, - XFER_COUNT_MID_REG = 0xd, - XFER_COUNT_HI_REG = 0xe, - TMS9914_BASE_REG = 0x10, - INTERNAL_CONFIG_REG = 0x18, - IMR0_READ_REG = 0x19, /* read */ - T1_DELAY_REG = 0x19, /* write */ - IMR1_READ_REG = 0x1a, - ADR_READ_REG = 0x1b, - SPMR_READ_REG = 0x1c, - PPR_READ_REG = 0x1d, - CDOR_READ_REG = 0x1e, - SRAM_ACCESS_CONTROL_REG = 0x1f, -}; - -enum card_mode_bits - -{ - ACTIVE_CONTROLLER_BIT = 0x2, /* read-only */ - CM_SYSTEM_CONTROLLER_BIT = 0x8, - ENABLE_BUS_MONITOR_BIT = 0x10, - ENABLE_PCI_IRQ_BIT = 0x20, -}; - -enum interrupt_enable_bits - -{ - ENABLE_TMS9914_INTERRUPTS_BIT = 0x1, - ENABLE_BUFFER_END_INTERRUPT_BIT = 0x10, - ENABLE_TERM_COUNT_INTERRUPT_BIT = 0x20, -}; - -enum event_enable_bits - -{ - ENABLE_BUFFER_END_EVENTS_BIT = 0x10, - ENABLE_TERM_COUNT_EVENTS_BIT = 0x20, -}; - -enum event_status_bits - -{ - TMS9914_IRQ_STATUS_BIT = 0x1, - IRQ_STATUS_BIT = 0x2, - BUFFER_END_STATUS_BIT = 0x10, /* write-clear */ - TERM_COUNT_STATUS_BIT = 0x20, /* write-clear */ -}; - -enum stream_status_bits - -{ - HALTED_STATUS_BIT = 0x1, /* read */ - RESTART_STREAM_BIT = 0x1, /* write */ -}; - -enum internal_config_bits - -{ - IC_SYSTEM_CONTROLLER_BIT = 0x80, -}; - -enum sram_access_control_bits - -{ - DIRECTION_GPIB_TO_HOST = 0x20, /* transfer direction */ - ENABLE_TI_TO_SRAM = 0x40, /* enable fifo */ - ENABLE_FAST_TALKER = 0x80 /* added for 82350A (not used) */ -}; - -enum borg_bits - -{ - BORG_READY_BIT = 0x40, - BORG_DONE_BIT = 0x80 -}; - -static const int agilent_82350b_fifo_size = 0x8000; - -static inline int agilent_82350b_fifo_is_halted(struct agilent_82350b_priv *a_priv) - -{ - return readb(a_priv->gpib_base + STREAM_STATUS_REG) & HALTED_STATUS_BIT; -} - diff --git a/drivers/staging/gpib/agilent_82357a/Makefile b/drivers/staging/gpib/agilent_82357a/Makefile deleted file mode 100644 index 81a55c257a6e..000000000000 --- a/drivers/staging/gpib/agilent_82357a/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -obj-$(CONFIG_GPIB_AGILENT_82357A) += agilent_82357a.o - - diff --git a/drivers/staging/gpib/agilent_82357a/agilent_82357a.c b/drivers/staging/gpib/agilent_82357a/agilent_82357a.c deleted file mode 100644 index 77c8e549b208..000000000000 --- a/drivers/staging/gpib/agilent_82357a/agilent_82357a.c +++ /dev/null @@ -1,1691 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * driver for Agilent 82357A/B usb to gpib adapters * - * copyright : (C) 2004 by Frank Mori Hess * - ***************************************************************************/ - -#define _GNU_SOURCE - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define DRV_NAME KBUILD_MODNAME - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include "agilent_82357a.h" -#include "gpibP.h" -#include "tms9914.h" - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB driver for Agilent 82357A/B usb adapters"); - -#define MAX_NUM_82357A_INTERFACES 128 -static struct usb_interface *agilent_82357a_driver_interfaces[MAX_NUM_82357A_INTERFACES]; -static DEFINE_MUTEX(agilent_82357a_hotplug_lock); // protect board insertion and removal - -static unsigned int agilent_82357a_update_status(struct gpib_board *board, - unsigned int clear_mask); - -static int agilent_82357a_take_control_internal(struct gpib_board *board, int synchronous); - -static void agilent_82357a_bulk_complete(struct urb *urb) -{ - struct agilent_82357a_urb_ctx *context = urb->context; - - complete(&context->complete); -} - -static void agilent_82357a_timeout_handler(struct timer_list *t) -{ - struct agilent_82357a_priv *a_priv = timer_container_of(a_priv, t, - bulk_timer); - struct agilent_82357a_urb_ctx *context = &a_priv->context; - - context->timed_out = 1; - complete(&context->complete); -} - -static int agilent_82357a_send_bulk_msg(struct agilent_82357a_priv *a_priv, void *data, - int data_length, int *actual_data_length, - int timeout_msecs) -{ - struct usb_device *usb_dev; - int retval; - unsigned int out_pipe; - struct agilent_82357a_urb_ctx *context = &a_priv->context; - - *actual_data_length = 0; - retval = mutex_lock_interruptible(&a_priv->bulk_alloc_lock); - if (retval) - return retval; - if (!a_priv->bus_interface) { - mutex_unlock(&a_priv->bulk_alloc_lock); - return -ENODEV; - } - if (a_priv->bulk_urb) { - mutex_unlock(&a_priv->bulk_alloc_lock); - return -EAGAIN; - } - a_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!a_priv->bulk_urb) { - mutex_unlock(&a_priv->bulk_alloc_lock); - return -ENOMEM; - } - usb_dev = interface_to_usbdev(a_priv->bus_interface); - out_pipe = usb_sndbulkpipe(usb_dev, a_priv->bulk_out_endpoint); - init_completion(&context->complete); - context->timed_out = 0; - usb_fill_bulk_urb(a_priv->bulk_urb, usb_dev, out_pipe, data, data_length, - &agilent_82357a_bulk_complete, context); - - if (timeout_msecs) - mod_timer(&a_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs)); - - retval = usb_submit_urb(a_priv->bulk_urb, GFP_KERNEL); - if (retval) { - dev_err(&usb_dev->dev, "failed to submit bulk out urb, retval=%i\n", retval); - mutex_unlock(&a_priv->bulk_alloc_lock); - goto cleanup; - } - mutex_unlock(&a_priv->bulk_alloc_lock); - if (wait_for_completion_interruptible(&context->complete)) { - retval = -ERESTARTSYS; - goto cleanup; - } - if (context->timed_out) { - retval = -ETIMEDOUT; - } else { - retval = a_priv->bulk_urb->status; - *actual_data_length = a_priv->bulk_urb->actual_length; - } -cleanup: - if (timeout_msecs) { - if (timer_pending(&a_priv->bulk_timer)) - timer_delete_sync(&a_priv->bulk_timer); - } - mutex_lock(&a_priv->bulk_alloc_lock); - if (a_priv->bulk_urb) { - usb_kill_urb(a_priv->bulk_urb); - usb_free_urb(a_priv->bulk_urb); - a_priv->bulk_urb = NULL; - } - mutex_unlock(&a_priv->bulk_alloc_lock); - return retval; -} - -static int agilent_82357a_receive_bulk_msg(struct agilent_82357a_priv *a_priv, void *data, - int data_length, int *actual_data_length, - int timeout_msecs) -{ - struct usb_device *usb_dev; - int retval; - unsigned int in_pipe; - struct agilent_82357a_urb_ctx *context = &a_priv->context; - - *actual_data_length = 0; - retval = mutex_lock_interruptible(&a_priv->bulk_alloc_lock); - if (retval) - return retval; - if (!a_priv->bus_interface) { - mutex_unlock(&a_priv->bulk_alloc_lock); - return -ENODEV; - } - if (a_priv->bulk_urb) { - mutex_unlock(&a_priv->bulk_alloc_lock); - return -EAGAIN; - } - a_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!a_priv->bulk_urb) { - mutex_unlock(&a_priv->bulk_alloc_lock); - return -ENOMEM; - } - usb_dev = interface_to_usbdev(a_priv->bus_interface); - in_pipe = usb_rcvbulkpipe(usb_dev, AGILENT_82357_BULK_IN_ENDPOINT); - init_completion(&context->complete); - context->timed_out = 0; - usb_fill_bulk_urb(a_priv->bulk_urb, usb_dev, in_pipe, data, data_length, - &agilent_82357a_bulk_complete, context); - - if (timeout_msecs) - mod_timer(&a_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs)); - - retval = usb_submit_urb(a_priv->bulk_urb, GFP_KERNEL); - if (retval) { - dev_err(&usb_dev->dev, "failed to submit bulk in urb, retval=%i\n", retval); - mutex_unlock(&a_priv->bulk_alloc_lock); - goto cleanup; - } - mutex_unlock(&a_priv->bulk_alloc_lock); - if (wait_for_completion_interruptible(&context->complete)) { - retval = -ERESTARTSYS; - goto cleanup; - } - if (context->timed_out) { - retval = -ETIMEDOUT; - goto cleanup; - } - retval = a_priv->bulk_urb->status; - *actual_data_length = a_priv->bulk_urb->actual_length; -cleanup: - if (timeout_msecs) - timer_delete_sync(&a_priv->bulk_timer); - - mutex_lock(&a_priv->bulk_alloc_lock); - if (a_priv->bulk_urb) { - usb_kill_urb(a_priv->bulk_urb); - usb_free_urb(a_priv->bulk_urb); - a_priv->bulk_urb = NULL; - } - mutex_unlock(&a_priv->bulk_alloc_lock); - return retval; -} - -static int agilent_82357a_receive_control_msg(struct agilent_82357a_priv *a_priv, __u8 request, - __u8 requesttype, __u16 value, __u16 index, - void *data, __u16 size, int timeout_msecs) -{ - struct usb_device *usb_dev; - int retval; - unsigned int in_pipe; - - retval = mutex_lock_interruptible(&a_priv->control_alloc_lock); - if (retval) - return retval; - if (!a_priv->bus_interface) { - mutex_unlock(&a_priv->control_alloc_lock); - return -ENODEV; - } - usb_dev = interface_to_usbdev(a_priv->bus_interface); - in_pipe = usb_rcvctrlpipe(usb_dev, AGILENT_82357_CONTROL_ENDPOINT); - retval = usb_control_msg(usb_dev, in_pipe, request, requesttype, value, index, data, - size, timeout_msecs); - mutex_unlock(&a_priv->control_alloc_lock); - return retval; -} - -static void agilent_82357a_dump_raw_block(const u8 *raw_data, int length) -{ - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 8, 1, raw_data, length, true); -} - -static int agilent_82357a_write_registers(struct agilent_82357a_priv *a_priv, - const struct agilent_82357a_register_pairlet *writes, - int num_writes) -{ - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); - int retval; - u8 *out_data, *in_data; - int out_data_length, in_data_length; - int bytes_written, bytes_read; - int i = 0; - int j; - static const int bytes_per_write = 2; - static const int header_length = 2; - static const int max_writes = 31; - - if (num_writes > max_writes) { - dev_err(&usb_dev->dev, "bug! num_writes=%i too large\n", num_writes); - return -EIO; - } - out_data_length = num_writes * bytes_per_write + header_length; - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return -ENOMEM; - - out_data[i++] = DATA_PIPE_CMD_WR_REGS; - out_data[i++] = num_writes; - for (j = 0; j < num_writes; j++) { - out_data[i++] = writes[j].address; - out_data[i++] = writes[j].value; - } - - retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock); - if (retval) { - kfree(out_data); - return retval; - } - retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, 1000); - kfree(out_data); - if (retval) { - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - retval, bytes_written, i); - mutex_unlock(&a_priv->bulk_transfer_lock); - return retval; - } - in_data_length = 0x20; - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) { - mutex_unlock(&a_priv->bulk_transfer_lock); - return -ENOMEM; - } - retval = agilent_82357a_receive_bulk_msg(a_priv, in_data, in_data_length, - &bytes_read, 1000); - mutex_unlock(&a_priv->bulk_transfer_lock); - - if (retval) { - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", - retval, bytes_read); - agilent_82357a_dump_raw_block(in_data, bytes_read); - kfree(in_data); - return -EIO; - } - if (in_data[0] != (0xff & ~DATA_PIPE_CMD_WR_REGS)) { - dev_err(&usb_dev->dev, "bulk command=0x%x != ~DATA_PIPE_CMD_WR_REGS\n", in_data[0]); - return -EIO; - } - if (in_data[1]) { - dev_err(&usb_dev->dev, "nonzero error code 0x%x in DATA_PIPE_CMD_WR_REGS response\n", - in_data[1]); - return -EIO; - } - kfree(in_data); - return 0; -} - -static int agilent_82357a_read_registers(struct agilent_82357a_priv *a_priv, - struct agilent_82357a_register_pairlet *reads, - int num_reads, int blocking) -{ - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); - int retval; - u8 *out_data, *in_data; - int out_data_length, in_data_length; - int bytes_written, bytes_read; - int i = 0; - int j; - static const int header_length = 2; - static const int max_reads = 62; - - if (num_reads > max_reads) { - dev_err(&usb_dev->dev, "bug! num_reads=%i too large\n", num_reads); - return -EIO; - } - out_data_length = num_reads + header_length; - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return -ENOMEM; - - out_data[i++] = DATA_PIPE_CMD_RD_REGS; - out_data[i++] = num_reads; - for (j = 0; j < num_reads; j++) - out_data[i++] = reads[j].address; - - if (blocking) { - retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock); - if (retval) { - kfree(out_data); - return retval; - } - } else { - retval = mutex_trylock(&a_priv->bulk_transfer_lock); - if (retval == 0) { - kfree(out_data); - return -EAGAIN; - } - } - retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, 1000); - kfree(out_data); - if (retval) { - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - retval, bytes_written, i); - mutex_unlock(&a_priv->bulk_transfer_lock); - return retval; - } - in_data_length = 0x20; - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) { - mutex_unlock(&a_priv->bulk_transfer_lock); - return -ENOMEM; - } - retval = agilent_82357a_receive_bulk_msg(a_priv, in_data, in_data_length, - &bytes_read, 10000); - mutex_unlock(&a_priv->bulk_transfer_lock); - - if (retval) { - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", - retval, bytes_read); - agilent_82357a_dump_raw_block(in_data, bytes_read); - kfree(in_data); - return -EIO; - } - i = 0; - if (in_data[i++] != (0xff & ~DATA_PIPE_CMD_RD_REGS)) { - dev_err(&usb_dev->dev, "bulk command=0x%x != ~DATA_PIPE_CMD_RD_REGS\n", in_data[0]); - return -EIO; - } - if (in_data[i++]) { - dev_err(&usb_dev->dev, "nonzero error code 0x%x in DATA_PIPE_CMD_RD_REGS response\n", - in_data[1]); - return -EIO; - } - for (j = 0; j < num_reads; j++) - reads[j].value = in_data[i++]; - kfree(in_data); - return 0; -} - -static int agilent_82357a_abort(struct agilent_82357a_priv *a_priv, int flush) -{ - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); - int retval = 0; - int receive_control_retval; - u16 wIndex = 0; - u8 *status_data; - static const unsigned int status_data_len = 2; - - status_data = kmalloc(status_data_len, GFP_KERNEL); - if (!status_data) - return -ENOMEM; - - if (flush) - wIndex |= XA_FLUSH; - receive_control_retval = agilent_82357a_receive_control_msg(a_priv, - agilent_82357a_control_request, - USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_DEVICE, XFER_ABORT, - wIndex, status_data, - status_data_len, 100); - if (receive_control_retval < 0) { - dev_err(&usb_dev->dev, "82357a_receive_control_msg() returned %i\n", - receive_control_retval); - retval = -EIO; - goto cleanup; - } - if (status_data[0] != (~XFER_ABORT & 0xff)) { - dev_err(&usb_dev->dev, "major code=0x%x != ~XFER_ABORT\n", status_data[0]); - retval = -EIO; - goto cleanup; - } - switch (status_data[1]) { - case UGP_SUCCESS: - retval = 0; - break; - case UGP_ERR_FLUSHING: - if (flush) { - retval = 0; - break; - } - fallthrough; - case UGP_ERR_FLUSHING_ALREADY: - default: - dev_err(&usb_dev->dev, "abort returned error code=0x%x\n", status_data[1]); - retval = -EIO; - break; - } - -cleanup: - kfree(status_data); - return retval; -} - -// interface functions -int agilent_82357a_command(struct gpib_board *board, u8 *buffer, size_t length, - size_t *bytes_written); - -static int agilent_82357a_read(struct gpib_board *board, u8 *buffer, size_t length, int *end, - size_t *nbytes) -{ - int retval; - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev; - u8 *out_data, *in_data; - int out_data_length, in_data_length; - int bytes_written, bytes_read; - int i = 0; - u8 trailing_flags; - unsigned long start_jiffies = jiffies; - int msec_timeout; - - *nbytes = 0; - *end = 0; - - if (!a_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(a_priv->bus_interface); - out_data_length = 0x9; - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return -ENOMEM; - out_data[i++] = DATA_PIPE_CMD_READ; - out_data[i++] = 0; // primary address when ARF_NO_ADDR is not set - out_data[i++] = 0; // secondary address when ARF_NO_ADDR is not set - out_data[i] = ARF_NO_ADDRESS | ARF_END_ON_EOI; - if (a_priv->eos_mode & REOS) - out_data[i] |= ARF_END_ON_EOS_CHAR; - ++i; - out_data[i++] = length & 0xff; - out_data[i++] = (length >> 8) & 0xff; - out_data[i++] = (length >> 16) & 0xff; - out_data[i++] = (length >> 24) & 0xff; - out_data[i++] = a_priv->eos_char; - msec_timeout = (board->usec_timeout + 999) / 1000; - retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock); - if (retval) { - kfree(out_data); - return retval; - } - retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, msec_timeout); - kfree(out_data); - if (retval || bytes_written != i) { - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - retval, bytes_written, i); - mutex_unlock(&a_priv->bulk_transfer_lock); - if (retval < 0) - return retval; - return -EIO; - } - in_data_length = length + 1; - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) { - mutex_unlock(&a_priv->bulk_transfer_lock); - return -ENOMEM; - } - if (board->usec_timeout != 0) - msec_timeout -= jiffies_to_msecs(jiffies - start_jiffies) - 1; - if (msec_timeout >= 0) { - retval = agilent_82357a_receive_bulk_msg(a_priv, in_data, in_data_length, - &bytes_read, msec_timeout); - } else { - retval = -ETIMEDOUT; - bytes_read = 0; - } - if (retval == -ETIMEDOUT) { - int extra_bytes_read; - int extra_bytes_retval; - - agilent_82357a_abort(a_priv, 1); - extra_bytes_retval = agilent_82357a_receive_bulk_msg(a_priv, in_data + bytes_read, - in_data_length - bytes_read, - &extra_bytes_read, 100); - bytes_read += extra_bytes_read; - if (extra_bytes_retval) { - dev_err(&usb_dev->dev, "extra_bytes_retval=%i, bytes_read=%i\n", - extra_bytes_retval, bytes_read); - agilent_82357a_abort(a_priv, 0); - } - } else if (retval) { - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", - retval, bytes_read); - agilent_82357a_abort(a_priv, 0); - } - mutex_unlock(&a_priv->bulk_transfer_lock); - if (bytes_read > length + 1) { - bytes_read = length + 1; - dev_warn(&usb_dev->dev, "bytes_read > length? truncating"); - } - - if (bytes_read >= 1) { - memcpy(buffer, in_data, bytes_read - 1); - trailing_flags = in_data[bytes_read - 1]; - *nbytes = bytes_read - 1; - if (trailing_flags & (ATRF_EOI | ATRF_EOS)) - *end = 1; - } - kfree(in_data); - - /* - * Fix for a bug in 9914A that does not return the contents of ADSR - * when the board is in listener active state and ATN is not asserted. - * Set ATN here to obtain a valid board level ibsta - */ - agilent_82357a_take_control_internal(board, 0); - - // FIXME check trailing flags for error - return retval; -} - -static ssize_t agilent_82357a_generic_write(struct gpib_board *board, - u8 *buffer, size_t length, - int send_commands, int send_eoi, - size_t *bytes_written) -{ - int retval; - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev; - u8 *out_data = NULL; - u8 *status_data = NULL; - int out_data_length; - int raw_bytes_written; - int i = 0, j; - int msec_timeout; - unsigned short bsr, adsr; - struct agilent_82357a_register_pairlet read_reg; - - *bytes_written = 0; - if (!a_priv->bus_interface) - return -ENODEV; - - usb_dev = interface_to_usbdev(a_priv->bus_interface); - out_data_length = length + 0x8; - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return -ENOMEM; - out_data[i++] = DATA_PIPE_CMD_WRITE; - out_data[i++] = 0; // primary address when AWF_NO_ADDRESS is not set - out_data[i++] = 0; // secondary address when AWF_NO_ADDRESS is not set - out_data[i] = AWF_NO_ADDRESS | AWF_NO_FAST_TALKER_FIRST_BYTE; - if (send_commands) - out_data[i] |= AWF_ATN | AWF_NO_FAST_TALKER; - if (send_eoi) - out_data[i] |= AWF_SEND_EOI; - ++i; - out_data[i++] = length & 0xff; - out_data[i++] = (length >> 8) & 0xff; - out_data[i++] = (length >> 16) & 0xff; - out_data[i++] = (length >> 24) & 0xff; - for (j = 0; j < length; j++) - out_data[i++] = buffer[j]; - - clear_bit(AIF_WRITE_COMPLETE_BN, &a_priv->interrupt_flags); - - msec_timeout = (board->usec_timeout + 999) / 1000; - retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock); - if (retval) { - kfree(out_data); - return retval; - } - retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &raw_bytes_written, - msec_timeout); - kfree(out_data); - if (retval || raw_bytes_written != i) { - agilent_82357a_abort(a_priv, 0); - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, raw_bytes_written=%i, i=%i\n", - retval, raw_bytes_written, i); - mutex_unlock(&a_priv->bulk_transfer_lock); - if (retval < 0) - return retval; - return -EIO; - } - - retval = wait_event_interruptible(board->wait, - test_bit(AIF_WRITE_COMPLETE_BN, - &a_priv->interrupt_flags) || - test_bit(TIMO_NUM, &board->status)); - if (retval) { - dev_dbg(&usb_dev->dev, "wait write complete interrupted\n"); - agilent_82357a_abort(a_priv, 0); - mutex_unlock(&a_priv->bulk_transfer_lock); - return -ERESTARTSYS; - } - - if (test_bit(AIF_WRITE_COMPLETE_BN, &a_priv->interrupt_flags) == 0) { - dev_dbg(&usb_dev->dev, "write timed out ibs %i, tmo %i\n", - test_bit(TIMO_NUM, &board->status), msec_timeout); - - agilent_82357a_abort(a_priv, 0); - - mutex_unlock(&a_priv->bulk_transfer_lock); - - read_reg.address = BSR; - retval = agilent_82357a_read_registers(a_priv, &read_reg, 1, 1); - if (retval) { - dev_err(&usb_dev->dev, "read_registers() returned error\n"); - return -ETIMEDOUT; - } - - bsr = read_reg.value; - dev_dbg(&usb_dev->dev, "write aborted bsr 0x%x\n", bsr); - - if (send_commands) {/* check for no listeners */ - if ((bsr & BSR_ATN_BIT) && !(bsr & (BSR_NDAC_BIT | BSR_NRFD_BIT))) { - dev_dbg(&usb_dev->dev, "No listener on command\n"); - clear_bit(TIMO_NUM, &board->status); - return -ENOTCONN; // no listener on bus - } - } else { - read_reg.address = ADSR; - retval = agilent_82357a_read_registers(a_priv, &read_reg, 1, 1); - if (retval) { - dev_err(&usb_dev->dev, "read_registers() returned error\n"); - return -ETIMEDOUT; - } - adsr = read_reg.value; - if ((adsr & HR_TA) && !(bsr & (BSR_NDAC_BIT | BSR_NRFD_BIT))) { - dev_dbg(&usb_dev->dev, "No listener on write\n"); - clear_bit(TIMO_NUM, &board->status); - return -ECOMM; - } - } - - return -ETIMEDOUT; - } - - status_data = kmalloc(STATUS_DATA_LEN, GFP_KERNEL); - if (!status_data) { - mutex_unlock(&a_priv->bulk_transfer_lock); - return -ENOMEM; - } - - retval = agilent_82357a_receive_control_msg(a_priv, agilent_82357a_control_request, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - XFER_STATUS, 0, status_data, STATUS_DATA_LEN, - 100); - mutex_unlock(&a_priv->bulk_transfer_lock); - if (retval < 0) { - dev_err(&usb_dev->dev, "receive_control_msg() returned %i\n", retval); - kfree(status_data); - return -EIO; - } - *bytes_written = (u32)status_data[2]; - *bytes_written |= (u32)status_data[3] << 8; - *bytes_written |= (u32)status_data[4] << 16; - *bytes_written |= (u32)status_data[5] << 24; - - kfree(status_data); - return 0; -} - -static int agilent_82357a_write(struct gpib_board *board, u8 *buffer, - size_t length, int send_eoi, size_t *bytes_written) -{ - return agilent_82357a_generic_write(board, buffer, length, 0, send_eoi, bytes_written); -} - -int agilent_82357a_command(struct gpib_board *board, u8 *buffer, size_t length, - size_t *bytes_written) -{ - return agilent_82357a_generic_write(board, buffer, length, 1, 0, bytes_written); -} - -int agilent_82357a_take_control_internal(struct gpib_board *board, int synchronous) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); - struct agilent_82357a_register_pairlet write; - int retval; - - write.address = AUXCR; - if (synchronous) - write.value = AUX_TCS; - else - write.value = AUX_TCA; - retval = agilent_82357a_write_registers(a_priv, &write, 1); - if (retval) - dev_err(&usb_dev->dev, "write_registers() returned error\n"); - - return retval; -} - -static int agilent_82357a_take_control(struct gpib_board *board, int synchronous) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - const int timeout = 10; - int i; - - if (!a_priv->bus_interface) - return -ENODEV; - -/* - * It looks like the 9914 does not handle tcs properly. - * See comment above tms9914_take_control_workaround() in - * drivers/gpib/tms9914/tms9914_aux.c - */ - if (synchronous) - return -ETIMEDOUT; - - agilent_82357a_take_control_internal(board, synchronous); - // busy wait until ATN is asserted - for (i = 0; i < timeout; ++i) { - agilent_82357a_update_status(board, 0); - if (test_bit(ATN_NUM, &board->status)) - break; - udelay(1); - } - if (i == timeout) - return -ETIMEDOUT; - return 0; -} - -static int agilent_82357a_go_to_standby(struct gpib_board *board) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev; - struct agilent_82357a_register_pairlet write; - int retval; - - if (!a_priv->bus_interface) - return -ENODEV; - - usb_dev = interface_to_usbdev(a_priv->bus_interface); - write.address = AUXCR; - write.value = AUX_GTS; - retval = agilent_82357a_write_registers(a_priv, &write, 1); - if (retval) - dev_err(&usb_dev->dev, "write_registers() returned error\n"); - return 0; -} - -static int agilent_82357a_request_system_control(struct gpib_board *board, int request_control) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev; - struct agilent_82357a_register_pairlet writes[2]; - int retval; - int i = 0; - - if (!a_priv->bus_interface) - return -ENODEV; - - usb_dev = interface_to_usbdev(a_priv->bus_interface); - /* 82357B needs bit to be set in 9914 AUXCR register */ - writes[i].address = AUXCR; - if (request_control) { - writes[i].value = AUX_RQC; - a_priv->hw_control_bits |= SYSTEM_CONTROLLER; - } else { - return -EINVAL; - } - ++i; - writes[i].address = HW_CONTROL; - writes[i].value = a_priv->hw_control_bits; - ++i; - retval = agilent_82357a_write_registers(a_priv, writes, i); - if (retval) - dev_err(&usb_dev->dev, "write_registers() returned error\n"); - return retval; -} - -static void agilent_82357a_interface_clear(struct gpib_board *board, int assert) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev; - struct agilent_82357a_register_pairlet write; - int retval; - - if (!a_priv->bus_interface) - return; // -ENODEV; - - usb_dev = interface_to_usbdev(a_priv->bus_interface); - write.address = AUXCR; - write.value = AUX_SIC; - if (assert) { - write.value |= AUX_CS; - a_priv->is_cic = 1; - } - retval = agilent_82357a_write_registers(a_priv, &write, 1); - if (retval) - dev_err(&usb_dev->dev, "write_registers() returned error\n"); -} - -static void agilent_82357a_remote_enable(struct gpib_board *board, int enable) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev; - struct agilent_82357a_register_pairlet write; - int retval; - - if (!a_priv->bus_interface) - return; //-ENODEV; - - usb_dev = interface_to_usbdev(a_priv->bus_interface); - write.address = AUXCR; - write.value = AUX_SRE; - if (enable) - write.value |= AUX_CS; - retval = agilent_82357a_write_registers(a_priv, &write, 1); - if (retval) - dev_err(&usb_dev->dev, "write_registers() returned error\n"); - a_priv->ren_state = enable; - return;// 0; -} - -static int agilent_82357a_enable_eos(struct gpib_board *board, u8 eos_byte, - int compare_8_bits) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - - if (!a_priv->bus_interface) - return -ENODEV; - if (compare_8_bits == 0) - return -EOPNOTSUPP; - - a_priv->eos_char = eos_byte; - a_priv->eos_mode = REOS | BIN; - return 0; -} - -static void agilent_82357a_disable_eos(struct gpib_board *board) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - - a_priv->eos_mode &= ~REOS; -} - -static unsigned int agilent_82357a_update_status(struct gpib_board *board, - unsigned int clear_mask) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev; - struct agilent_82357a_register_pairlet address_status, bus_status; - int retval; - - if (!a_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(a_priv->bus_interface); - board->status &= ~clear_mask; - if (a_priv->is_cic) - set_bit(CIC_NUM, &board->status); - else - clear_bit(CIC_NUM, &board->status); - address_status.address = ADSR; - retval = agilent_82357a_read_registers(a_priv, &address_status, 1, 0); - if (retval) { - if (retval != -EAGAIN) - dev_err(&usb_dev->dev, "read_registers() returned error\n"); - return board->status; - } - // check for remote/local - if (address_status.value & HR_REM) - set_bit(REM_NUM, &board->status); - else - clear_bit(REM_NUM, &board->status); - // check for lockout - if (address_status.value & HR_LLO) - set_bit(LOK_NUM, &board->status); - else - clear_bit(LOK_NUM, &board->status); - // check for ATN - if (address_status.value & HR_ATN) - set_bit(ATN_NUM, &board->status); - else - clear_bit(ATN_NUM, &board->status); - // check for talker/listener addressed - if (address_status.value & HR_TA) - set_bit(TACS_NUM, &board->status); - else - clear_bit(TACS_NUM, &board->status); - if (address_status.value & HR_LA) - set_bit(LACS_NUM, &board->status); - else - clear_bit(LACS_NUM, &board->status); - - bus_status.address = BSR; - retval = agilent_82357a_read_registers(a_priv, &bus_status, 1, 0); - if (retval) { - if (retval != -EAGAIN) - dev_err(&usb_dev->dev, "read_registers() returned error\n"); - return board->status; - } - if (bus_status.value & BSR_SRQ_BIT) - set_bit(SRQI_NUM, &board->status); - else - clear_bit(SRQI_NUM, &board->status); - - return board->status; -} - -static int agilent_82357a_primary_address(struct gpib_board *board, unsigned int address) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); - struct agilent_82357a_register_pairlet write; - int retval; - - if (!a_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(a_priv->bus_interface); - // put primary address in address0 - write.address = ADR; - write.value = address & ADDRESS_MASK; - retval = agilent_82357a_write_registers(a_priv, &write, 1); - if (retval) { - dev_err(&usb_dev->dev, "write_registers() returned error\n"); - return retval; - } - return retval; -} - -static int agilent_82357a_secondary_address(struct gpib_board *board, - unsigned int address, int enable) -{ - if (enable) - return -EOPNOTSUPP; - return 0; -} - -static int agilent_82357a_parallel_poll(struct gpib_board *board, u8 *result) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev; - struct agilent_82357a_register_pairlet writes[2]; - struct agilent_82357a_register_pairlet read; - int retval; - - if (!a_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(a_priv->bus_interface); - // execute parallel poll - writes[0].address = AUXCR; - writes[0].value = AUX_CS | AUX_RPP; - writes[1].address = HW_CONTROL; - writes[1].value = a_priv->hw_control_bits & ~NOT_PARALLEL_POLL; - retval = agilent_82357a_write_registers(a_priv, writes, 2); - if (retval) { - dev_err(&usb_dev->dev, "write_registers() returned error\n"); - return retval; - } - udelay(2); // silly, since usb write will take way longer - read.address = CPTR; - retval = agilent_82357a_read_registers(a_priv, &read, 1, 1); - if (retval) { - dev_err(&usb_dev->dev, "read_registers() returned error\n"); - return retval; - } - *result = read.value; - // clear parallel poll state - writes[0].address = HW_CONTROL; - writes[0].value = a_priv->hw_control_bits | NOT_PARALLEL_POLL; - writes[1].address = AUXCR; - writes[1].value = AUX_RPP; - retval = agilent_82357a_write_registers(a_priv, writes, 2); - if (retval) { - dev_err(&usb_dev->dev, "write_registers() returned error\n"); - return retval; - } - return 0; -} - -static void agilent_82357a_parallel_poll_configure(struct gpib_board *board, u8 config) -{ - // board can only be system controller - return;// 0; -} - -static void agilent_82357a_parallel_poll_response(struct gpib_board *board, int ist) -{ - // board can only be system controller - return;// 0; -} - -static void agilent_82357a_serial_poll_response(struct gpib_board *board, u8 status) -{ - // board can only be system controller - return;// 0; -} - -static u8 agilent_82357a_serial_poll_status(struct gpib_board *board) -{ - // board can only be system controller - return 0; -} - -static void agilent_82357a_return_to_local(struct gpib_board *board) -{ - // board can only be system controller - return;// 0; -} - -static int agilent_82357a_line_status(const struct gpib_board *board) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev; - struct agilent_82357a_register_pairlet bus_status; - int retval; - int status = VALID_ALL; - - if (!a_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(a_priv->bus_interface); - bus_status.address = BSR; - retval = agilent_82357a_read_registers(a_priv, &bus_status, 1, 0); - if (retval) { - if (retval != -EAGAIN) - dev_err(&usb_dev->dev, "read_registers() returned error\n"); - return retval; - } - if (bus_status.value & BSR_REN_BIT) - status |= BUS_REN; - if (bus_status.value & BSR_IFC_BIT) - status |= BUS_IFC; - if (bus_status.value & BSR_SRQ_BIT) - status |= BUS_SRQ; - if (bus_status.value & BSR_EOI_BIT) - status |= BUS_EOI; - if (bus_status.value & BSR_NRFD_BIT) - status |= BUS_NRFD; - if (bus_status.value & BSR_NDAC_BIT) - status |= BUS_NDAC; - if (bus_status.value & BSR_DAV_BIT) - status |= BUS_DAV; - if (bus_status.value & BSR_ATN_BIT) - status |= BUS_ATN; - return status; -} - -static unsigned short nanosec_to_fast_talker_bits(unsigned int *nanosec) -{ - static const int nanosec_per_bit = 21; - static const int max_value = 0x72; - static const int min_value = 0x11; - unsigned short bits; - - bits = (*nanosec + nanosec_per_bit / 2) / nanosec_per_bit; - if (bits < min_value) - bits = min_value; - if (bits > max_value) - bits = max_value; - *nanosec = bits * nanosec_per_bit; - return bits; -} - -static int agilent_82357a_t1_delay(struct gpib_board *board, unsigned int nanosec) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev; - struct agilent_82357a_register_pairlet write; - int retval; - - if (!a_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(a_priv->bus_interface); - write.address = FAST_TALKER_T1; - write.value = nanosec_to_fast_talker_bits(&nanosec); - retval = agilent_82357a_write_registers(a_priv, &write, 1); - if (retval) - dev_err(&usb_dev->dev, "write_registers() returned error\n"); - return nanosec; -} - -static void agilent_82357a_interrupt_complete(struct urb *urb) -{ - struct gpib_board *board = urb->context; - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); - int retval; - u8 *transfer_buffer = urb->transfer_buffer; - unsigned long interrupt_flags; - - switch (urb->status) { - /* success */ - case 0: - break; - /* unlinked, don't resubmit */ - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* other error, resubmit */ - retval = usb_submit_urb(a_priv->interrupt_urb, GFP_ATOMIC); - if (retval) - dev_err(&usb_dev->dev, "failed to resubmit interrupt urb\n"); - return; - } - - interrupt_flags = transfer_buffer[0]; - if (test_bit(AIF_READ_COMPLETE_BN, &interrupt_flags)) - set_bit(AIF_READ_COMPLETE_BN, &a_priv->interrupt_flags); - if (test_bit(AIF_WRITE_COMPLETE_BN, &interrupt_flags)) - set_bit(AIF_WRITE_COMPLETE_BN, &a_priv->interrupt_flags); - if (test_bit(AIF_SRQ_BN, &interrupt_flags)) - set_bit(SRQI_NUM, &board->status); - - wake_up_interruptible(&board->wait); - - retval = usb_submit_urb(a_priv->interrupt_urb, GFP_ATOMIC); - if (retval) - dev_err(&usb_dev->dev, "failed to resubmit interrupt urb\n"); -} - -static int agilent_82357a_setup_urbs(struct gpib_board *board) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev; - int int_pipe; - int retval; - - retval = mutex_lock_interruptible(&a_priv->interrupt_alloc_lock); - if (retval) - return retval; - if (!a_priv->bus_interface) { - retval = -ENODEV; - goto setup_exit; - } - - a_priv->interrupt_buffer = kmalloc(INTERRUPT_BUF_LEN, GFP_KERNEL); - if (!a_priv->interrupt_buffer) { - retval = -ENOMEM; - goto setup_exit; - } - a_priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!a_priv->interrupt_urb) { - retval = -ENOMEM; - goto setup_exit; - } - usb_dev = interface_to_usbdev(a_priv->bus_interface); - int_pipe = usb_rcvintpipe(usb_dev, a_priv->interrupt_in_endpoint); - usb_fill_int_urb(a_priv->interrupt_urb, usb_dev, int_pipe, a_priv->interrupt_buffer, - INTERRUPT_BUF_LEN, &agilent_82357a_interrupt_complete, board, 1); - retval = usb_submit_urb(a_priv->interrupt_urb, GFP_KERNEL); - if (retval) { - usb_free_urb(a_priv->interrupt_urb); - a_priv->interrupt_urb = NULL; - dev_err(&usb_dev->dev, "failed to submit first interrupt urb, retval=%i\n", retval); - goto setup_exit; - } - mutex_unlock(&a_priv->interrupt_alloc_lock); - return 0; - -setup_exit: - kfree(a_priv->interrupt_buffer); - mutex_unlock(&a_priv->interrupt_alloc_lock); - return retval; -} - -static void agilent_82357a_cleanup_urbs(struct agilent_82357a_priv *a_priv) -{ - if (a_priv && a_priv->bus_interface) { - if (a_priv->interrupt_urb) - usb_kill_urb(a_priv->interrupt_urb); - if (a_priv->bulk_urb) - usb_kill_urb(a_priv->bulk_urb); - } -}; - -static void agilent_82357a_release_urbs(struct agilent_82357a_priv *a_priv) -{ - if (a_priv) { - usb_free_urb(a_priv->interrupt_urb); - a_priv->interrupt_urb = NULL; - kfree(a_priv->interrupt_buffer); - } -} - -static int agilent_82357a_allocate_private(struct gpib_board *board) -{ - struct agilent_82357a_priv *a_priv; - - board->private_data = kzalloc(sizeof(struct agilent_82357a_priv), GFP_KERNEL); - if (!board->private_data) - return -ENOMEM; - a_priv = board->private_data; - mutex_init(&a_priv->bulk_transfer_lock); - mutex_init(&a_priv->bulk_alloc_lock); - mutex_init(&a_priv->control_alloc_lock); - mutex_init(&a_priv->interrupt_alloc_lock); - return 0; -} - -static void agilent_82357a_free_private(struct gpib_board *board) -{ - kfree(board->private_data); - board->private_data = NULL; -} - -#define INIT_NUM_REG_WRITES 18 -static int agilent_82357a_init(struct gpib_board *board) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); - struct agilent_82357a_register_pairlet hw_control; - struct agilent_82357a_register_pairlet writes[INIT_NUM_REG_WRITES]; - int retval; - unsigned int nanosec; - - writes[0].address = LED_CONTROL; - writes[0].value = FAIL_LED_ON; - writes[1].address = RESET_TO_POWERUP; - writes[1].value = RESET_SPACEBALL; - retval = agilent_82357a_write_registers(a_priv, writes, 2); - if (retval) { - dev_err(&usb_dev->dev, "write_registers() returned error\n"); - return -EIO; - } - set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout(usec_to_jiffies(2000))) - return -ERESTARTSYS; - writes[0].address = AUXCR; - writes[0].value = AUX_NBAF; - writes[1].address = AUXCR; - writes[1].value = AUX_HLDE; - writes[2].address = AUXCR; - writes[2].value = AUX_TON; - writes[3].address = AUXCR; - writes[3].value = AUX_LON; - writes[4].address = AUXCR; - writes[4].value = AUX_RSV2; - writes[5].address = AUXCR; - writes[5].value = AUX_INVAL; - writes[6].address = AUXCR; - writes[6].value = AUX_RPP; - writes[7].address = AUXCR; - writes[7].value = AUX_STDL; - writes[8].address = AUXCR; - writes[8].value = AUX_VSTDL; - writes[9].address = FAST_TALKER_T1; - nanosec = board->t1_nano_sec; - writes[9].value = nanosec_to_fast_talker_bits(&nanosec); - board->t1_nano_sec = nanosec; - writes[10].address = ADR; - writes[10].value = board->pad & ADDRESS_MASK; - writes[11].address = PPR; - writes[11].value = 0; - writes[12].address = SPMR; - writes[12].value = 0; - writes[13].address = PROTOCOL_CONTROL; - writes[13].value = WRITE_COMPLETE_INTERRUPT_EN; - writes[14].address = IMR0; - writes[14].value = HR_BOIE | HR_BIIE; - writes[15].address = IMR1; - writes[15].value = HR_SRQIE; - // turn off reset state - writes[16].address = AUXCR; - writes[16].value = AUX_CHIP_RESET; - writes[17].address = LED_CONTROL; - writes[17].value = FIRMWARE_LED_CONTROL; - retval = agilent_82357a_write_registers(a_priv, writes, INIT_NUM_REG_WRITES); - if (retval) { - dev_err(&usb_dev->dev, "write_registers() returned error\n"); - return -EIO; - } - hw_control.address = HW_CONTROL; - retval = agilent_82357a_read_registers(a_priv, &hw_control, 1, 1); - if (retval) { - dev_err(&usb_dev->dev, "read_registers() returned error\n"); - return -EIO; - } - a_priv->hw_control_bits = (hw_control.value & ~0x7) | NOT_TI_RESET | NOT_PARALLEL_POLL; - - return 0; -} - -static inline int agilent_82357a_device_match(struct usb_interface *interface, - const struct gpib_board_config *config) -{ - struct usb_device * const usbdev = interface_to_usbdev(interface); - - if (gpib_match_device_path(&interface->dev, config->device_path) == 0) - return 0; - if (config->serial_number && - strcmp(usbdev->serial, config->serial_number) != 0) - return 0; - - return 1; -} - -static int agilent_82357a_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - int retval; - int i; - unsigned int product_id; - struct agilent_82357a_priv *a_priv; - struct usb_device *usb_dev; - - if (mutex_lock_interruptible(&agilent_82357a_hotplug_lock)) - return -ERESTARTSYS; - - retval = agilent_82357a_allocate_private(board); - if (retval < 0) { - mutex_unlock(&agilent_82357a_hotplug_lock); - return retval; - } - a_priv = board->private_data; - for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) { - if (agilent_82357a_driver_interfaces[i] && - !usb_get_intfdata(agilent_82357a_driver_interfaces[i]) && - agilent_82357a_device_match(agilent_82357a_driver_interfaces[i], config)) { - a_priv->bus_interface = agilent_82357a_driver_interfaces[i]; - usb_set_intfdata(agilent_82357a_driver_interfaces[i], board); - usb_dev = interface_to_usbdev(a_priv->bus_interface); - break; - } - } - if (i == MAX_NUM_82357A_INTERFACES) { - dev_err(board->gpib_dev, - "No supported adapters found, have you loaded its firmware?\n"); - retval = -ENODEV; - goto attach_fail; - } - product_id = le16_to_cpu(interface_to_usbdev(a_priv->bus_interface)->descriptor.idProduct); - switch (product_id) { - case USB_DEVICE_ID_AGILENT_82357A: - a_priv->bulk_out_endpoint = AGILENT_82357A_BULK_OUT_ENDPOINT; - a_priv->interrupt_in_endpoint = AGILENT_82357A_INTERRUPT_IN_ENDPOINT; - break; - case USB_DEVICE_ID_AGILENT_82357B: - a_priv->bulk_out_endpoint = AGILENT_82357B_BULK_OUT_ENDPOINT; - a_priv->interrupt_in_endpoint = AGILENT_82357B_INTERRUPT_IN_ENDPOINT; - break; - default: - dev_err(&usb_dev->dev, "bug, unhandled product_id in switch?\n"); - retval = -EIO; - goto attach_fail; - } - - retval = agilent_82357a_setup_urbs(board); - if (retval < 0) - goto attach_fail; - - timer_setup(&a_priv->bulk_timer, agilent_82357a_timeout_handler, 0); - - board->t1_nano_sec = 800; - - retval = agilent_82357a_init(board); - - if (retval < 0) { - agilent_82357a_cleanup_urbs(a_priv); - agilent_82357a_release_urbs(a_priv); - goto attach_fail; - } - - dev_info(&usb_dev->dev, "bus %d dev num %d attached to gpib%d, interface %i\n", - usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); - mutex_unlock(&agilent_82357a_hotplug_lock); - return retval; - -attach_fail: - agilent_82357a_free_private(board); - mutex_unlock(&agilent_82357a_hotplug_lock); - return retval; -} - -static int agilent_82357a_go_idle(struct gpib_board *board) -{ - struct agilent_82357a_priv *a_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface); - struct agilent_82357a_register_pairlet writes[0x20]; - int retval; - - // turn on tms9914 reset state - writes[0].address = AUXCR; - writes[0].value = AUX_CS | AUX_CHIP_RESET; - a_priv->hw_control_bits &= ~NOT_TI_RESET; - writes[1].address = HW_CONTROL; - writes[1].value = a_priv->hw_control_bits; - writes[2].address = PROTOCOL_CONTROL; - writes[2].value = 0; - writes[3].address = IMR0; - writes[3].value = 0; - writes[4].address = IMR1; - writes[4].value = 0; - writes[5].address = LED_CONTROL; - writes[5].value = 0; - retval = agilent_82357a_write_registers(a_priv, writes, 6); - if (retval) { - dev_err(&usb_dev->dev, "write_registers() returned error\n"); - return -EIO; - } - return 0; -} - -static void agilent_82357a_detach(struct gpib_board *board) -{ - struct agilent_82357a_priv *a_priv; - - mutex_lock(&agilent_82357a_hotplug_lock); - - a_priv = board->private_data; - if (a_priv) { - if (a_priv->bus_interface) { - agilent_82357a_go_idle(board); - usb_set_intfdata(a_priv->bus_interface, NULL); - } - mutex_lock(&a_priv->control_alloc_lock); - mutex_lock(&a_priv->bulk_alloc_lock); - mutex_lock(&a_priv->interrupt_alloc_lock); - agilent_82357a_cleanup_urbs(a_priv); - agilent_82357a_release_urbs(a_priv); - agilent_82357a_free_private(board); - } - mutex_unlock(&agilent_82357a_hotplug_lock); -} - -static struct gpib_interface agilent_82357a_gpib_interface = { - .name = "agilent_82357a", - .attach = agilent_82357a_attach, - .detach = agilent_82357a_detach, - .read = agilent_82357a_read, - .write = agilent_82357a_write, - .command = agilent_82357a_command, - .take_control = agilent_82357a_take_control, - .go_to_standby = agilent_82357a_go_to_standby, - .request_system_control = agilent_82357a_request_system_control, - .interface_clear = agilent_82357a_interface_clear, - .remote_enable = agilent_82357a_remote_enable, - .enable_eos = agilent_82357a_enable_eos, - .disable_eos = agilent_82357a_disable_eos, - .parallel_poll = agilent_82357a_parallel_poll, - .parallel_poll_configure = agilent_82357a_parallel_poll_configure, - .parallel_poll_response = agilent_82357a_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = agilent_82357a_line_status, - .update_status = agilent_82357a_update_status, - .primary_address = agilent_82357a_primary_address, - .secondary_address = agilent_82357a_secondary_address, - .serial_poll_response = agilent_82357a_serial_poll_response, - .serial_poll_status = agilent_82357a_serial_poll_status, - .t1_delay = agilent_82357a_t1_delay, - .return_to_local = agilent_82357a_return_to_local, - .no_7_bit_eos = 1, - .skip_check_for_command_acceptors = 1 -}; - -// Table with the USB-devices: just now only testing IDs -static struct usb_device_id agilent_82357a_driver_device_table[] = { - {USB_DEVICE(USB_VENDOR_ID_AGILENT, USB_DEVICE_ID_AGILENT_82357A)}, - {USB_DEVICE(USB_VENDOR_ID_AGILENT, USB_DEVICE_ID_AGILENT_82357B)}, - {} /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, agilent_82357a_driver_device_table); - -static int agilent_82357a_driver_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - int i; - char *path; - static const int path_length = 1024; - struct usb_device *usb_dev; - - if (mutex_lock_interruptible(&agilent_82357a_hotplug_lock)) - return -ERESTARTSYS; - usb_dev = usb_get_dev(interface_to_usbdev(interface)); - for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) { - if (!agilent_82357a_driver_interfaces[i]) { - agilent_82357a_driver_interfaces[i] = interface; - usb_set_intfdata(interface, NULL); - dev_dbg(&usb_dev->dev, "set bus interface %i to address 0x%p\n", - i, interface); - break; - } - } - if (i == MAX_NUM_82357A_INTERFACES) { - usb_put_dev(usb_dev); - mutex_unlock(&agilent_82357a_hotplug_lock); - dev_err(&usb_dev->dev, "out of space in agilent_82357a_driver_interfaces[]\n"); - return -1; - } - path = kmalloc(path_length, GFP_KERNEL); - if (!path) { - usb_put_dev(usb_dev); - mutex_unlock(&agilent_82357a_hotplug_lock); - return -ENOMEM; - } - usb_make_path(usb_dev, path, path_length); - dev_info(&usb_dev->dev, "probe succeeded for path: %s\n", path); - kfree(path); - mutex_unlock(&agilent_82357a_hotplug_lock); - return 0; -} - -static void agilent_82357a_driver_disconnect(struct usb_interface *interface) -{ - int i; - struct usb_device *usb_dev = interface_to_usbdev(interface); - - mutex_lock(&agilent_82357a_hotplug_lock); - - for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) { - if (agilent_82357a_driver_interfaces[i] == interface) { - struct gpib_board *board = usb_get_intfdata(interface); - - if (board) { - struct agilent_82357a_priv *a_priv = board->private_data; - - if (a_priv) { - mutex_lock(&a_priv->control_alloc_lock); - mutex_lock(&a_priv->bulk_alloc_lock); - mutex_lock(&a_priv->interrupt_alloc_lock); - agilent_82357a_cleanup_urbs(a_priv); - a_priv->bus_interface = NULL; - mutex_unlock(&a_priv->interrupt_alloc_lock); - mutex_unlock(&a_priv->bulk_alloc_lock); - mutex_unlock(&a_priv->control_alloc_lock); - } - } - agilent_82357a_driver_interfaces[i] = NULL; - break; - } - } - if (i == MAX_NUM_82357A_INTERFACES) - dev_err(&usb_dev->dev, "unable to find interface - bug?\n"); - usb_put_dev(usb_dev); - - mutex_unlock(&agilent_82357a_hotplug_lock); -} - -static int agilent_82357a_driver_suspend(struct usb_interface *interface, pm_message_t message) -{ - int i, retval; - struct usb_device *usb_dev = interface_to_usbdev(interface); - - mutex_lock(&agilent_82357a_hotplug_lock); - - for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) { - if (agilent_82357a_driver_interfaces[i] == interface) { - struct gpib_board *board = usb_get_intfdata(interface); - - if (board) { - struct agilent_82357a_priv *a_priv = board->private_data; - - if (a_priv) { - agilent_82357a_abort(a_priv, 0); - agilent_82357a_abort(a_priv, 0); - retval = agilent_82357a_go_idle(board); - if (retval) { - dev_err(&usb_dev->dev, "failed to go idle, retval=%i\n", - retval); - mutex_unlock(&agilent_82357a_hotplug_lock); - return retval; - } - mutex_lock(&a_priv->interrupt_alloc_lock); - agilent_82357a_cleanup_urbs(a_priv); - mutex_unlock(&a_priv->interrupt_alloc_lock); - dev_dbg(&usb_dev->dev, - "bus %d dev num %d gpib %d, interface %i suspended\n", - usb_dev->bus->busnum, usb_dev->devnum, - board->minor, i); - } - } - break; - } - } - - mutex_unlock(&agilent_82357a_hotplug_lock); - - return 0; -} - -static int agilent_82357a_driver_resume(struct usb_interface *interface) -{ - struct usb_device *usb_dev = interface_to_usbdev(interface); - struct gpib_board *board; - int i, retval = 0; - - mutex_lock(&agilent_82357a_hotplug_lock); - - for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) { - if (agilent_82357a_driver_interfaces[i] == interface) { - board = usb_get_intfdata(interface); - if (board) - break; - } - } - if (i == MAX_NUM_82357A_INTERFACES) { - retval = -ENOENT; - goto resume_exit; - } - - struct agilent_82357a_priv *a_priv = board->private_data; - - if (a_priv) { - if (a_priv->interrupt_urb) { - mutex_lock(&a_priv->interrupt_alloc_lock); - retval = usb_submit_urb(a_priv->interrupt_urb, GFP_KERNEL); - if (retval) { - dev_err(&usb_dev->dev, "failed to resubmit interrupt urb in resume, retval=%i\n", - retval); - mutex_unlock(&a_priv->interrupt_alloc_lock); - mutex_unlock(&agilent_82357a_hotplug_lock); - return retval; - } - mutex_unlock(&a_priv->interrupt_alloc_lock); - } - retval = agilent_82357a_init(board); - if (retval < 0) { - mutex_unlock(&agilent_82357a_hotplug_lock); - return retval; - } - // set/unset system controller - retval = agilent_82357a_request_system_control(board, board->master); - // toggle ifc if master - if (board->master) { - agilent_82357a_interface_clear(board, 1); - usleep_range(200, 250); - agilent_82357a_interface_clear(board, 0); - } - // assert/unassert REN - agilent_82357a_remote_enable(board, a_priv->ren_state); - - dev_dbg(&usb_dev->dev, - "bus %d dev num %d gpib%d, interface %i resumed\n", - usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); - } - -resume_exit: - mutex_unlock(&agilent_82357a_hotplug_lock); - - return retval; -} - -static struct usb_driver agilent_82357a_bus_driver = { - .name = DRV_NAME, - .probe = agilent_82357a_driver_probe, - .disconnect = agilent_82357a_driver_disconnect, - .suspend = agilent_82357a_driver_suspend, - .resume = agilent_82357a_driver_resume, - .id_table = agilent_82357a_driver_device_table, -}; - -static int __init agilent_82357a_init_module(void) -{ - int i; - int ret; - - for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) - agilent_82357a_driver_interfaces[i] = NULL; - - ret = usb_register(&agilent_82357a_bus_driver); - if (ret) { - pr_err("usb_register failed: error = %d\n", ret); - return ret; - } - - ret = gpib_register_driver(&agilent_82357a_gpib_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - usb_deregister(&agilent_82357a_bus_driver); - return ret; - } - - return 0; -} - -static void __exit agilent_82357a_exit_module(void) -{ - gpib_unregister_driver(&agilent_82357a_gpib_interface); - usb_deregister(&agilent_82357a_bus_driver); -} - -module_init(agilent_82357a_init_module); -module_exit(agilent_82357a_exit_module); diff --git a/drivers/staging/gpib/agilent_82357a/agilent_82357a.h b/drivers/staging/gpib/agilent_82357a/agilent_82357a.h deleted file mode 100644 index 33ac558e5552..000000000000 --- a/drivers/staging/gpib/agilent_82357a/agilent_82357a.h +++ /dev/null @@ -1,182 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2004 by Frank Mori Hess * - ***************************************************************************/ - -#include <linux/kernel.h> -#include <linux/mutex.h> -#include <linux/completion.h> -#include <linux/usb.h> -#include <linux/timer.h> -#include <linux/compiler_attributes.h> -#include "gpibP.h" -#include "tms9914.h" - -enum usb_vendor_ids { - USB_VENDOR_ID_AGILENT = 0x0957 -}; - -enum usb_device_ids { - USB_DEVICE_ID_AGILENT_82357A = 0x0107, - USB_DEVICE_ID_AGILENT_82357A_PREINIT = 0x0007, // device id before firmware is loaded - USB_DEVICE_ID_AGILENT_82357B = 0x0718, // device id before firmware is loaded - USB_DEVICE_ID_AGILENT_82357B_PREINIT = 0x0518, // device id before firmware is loaded -}; - -enum endpoint_addresses { - AGILENT_82357_CONTROL_ENDPOINT = 0x0, - AGILENT_82357_BULK_IN_ENDPOINT = 0x2, - AGILENT_82357A_BULK_OUT_ENDPOINT = 0x4, - AGILENT_82357A_INTERRUPT_IN_ENDPOINT = 0x6, - AGILENT_82357B_BULK_OUT_ENDPOINT = 0x6, - AGILENT_82357B_INTERRUPT_IN_ENDPOINT = 0x8, -}; - -enum bulk_commands { - DATA_PIPE_CMD_WRITE = 0x1, - DATA_PIPE_CMD_READ = 0x3, - DATA_PIPE_CMD_WR_REGS = 0x4, - DATA_PIPE_CMD_RD_REGS = 0x5 -}; - -enum agilent_82357a_read_flags { - ARF_END_ON_EOI = 0x1, - ARF_NO_ADDRESS = 0x2, - ARF_END_ON_EOS_CHAR = 0x4, - ARF_SPOLL = 0x8 -}; - -enum agilent_82357a_trailing_read_flags { - ATRF_EOI = 0x1, - ATRF_ATN = 0x2, - ATRF_IFC = 0x4, - ATRF_EOS = 0x8, - ATRF_ABORT = 0x10, - ATRF_COUNT = 0x20, - ATRF_DEAD_BUS = 0x40, - ATRF_UNADDRESSED = 0x80 -}; - -enum agilent_82357a_write_flags { - AWF_SEND_EOI = 0x1, - AWF_NO_FAST_TALKER_FIRST_BYTE = 0x2, - AWF_NO_FAST_TALKER = 0x4, - AWF_NO_ADDRESS = 0x8, - AWF_ATN = 0x10, - AWF_SEPARATE_HEADER = 0x80 -}; - -enum agilent_82357a_interrupt_flag_bit_numbers { - AIF_SRQ_BN = 0, - AIF_WRITE_COMPLETE_BN = 1, - AIF_READ_COMPLETE_BN = 2, -}; - -enum agilent_82357_error_codes { - UGP_SUCCESS = 0, - UGP_ERR_INVALID_CMD = 1, - UGP_ERR_INVALID_PARAM = 2, - UGP_ERR_INVALID_REG = 3, - UGP_ERR_GPIB_READ = 4, - UGP_ERR_GPIB_WRITE = 5, - UGP_ERR_FLUSHING = 6, - UGP_ERR_FLUSHING_ALREADY = 7, - UGP_ERR_UNSUPPORTED = 8, - UGP_ERR_OTHER = 9 -}; - -enum agilent_82357_control_values { - XFER_ABORT = 0xa0, - XFER_STATUS = 0xb0, -}; - -enum xfer_status_bits { - XS_COMPLETED = 0x1, - XS_READ = 0x2, -}; - -enum xfer_status_completion_bits { - XSC_EOI = 0x1, - XSC_ATN = 0x2, - XSC_IFC = 0x4, - XSC_EOS = 0x8, - XSC_ABORT = 0x10, - XSC_COUNT = 0x20, - XSC_DEAD_BUS = 0x40, - XSC_BUS_NOT_ADDRESSED = 0x80 -}; - -enum xfer_abort_type { - XA_FLUSH = 0x1 -}; - -#define STATUS_DATA_LEN 8 -#define INTERRUPT_BUF_LEN 8 - -struct agilent_82357a_urb_ctx { - struct completion complete; - unsigned timed_out : 1; -}; - -// struct which defines local data for each 82357 device -struct agilent_82357a_priv { - struct usb_interface *bus_interface; - unsigned short eos_char; - unsigned short eos_mode; - unsigned short hw_control_bits; - unsigned long interrupt_flags; - struct urb *bulk_urb; - struct urb *interrupt_urb; - u8 *interrupt_buffer; - struct mutex bulk_transfer_lock; // bulk transfer lock - struct mutex bulk_alloc_lock; // bulk transfer allocation lock - struct mutex interrupt_alloc_lock; // interrupt allocation lock - struct mutex control_alloc_lock; // control message allocation lock - struct timer_list bulk_timer; - struct agilent_82357a_urb_ctx context; - unsigned int bulk_out_endpoint; - unsigned int interrupt_in_endpoint; - unsigned is_cic : 1; - unsigned ren_state : 1; -}; - -struct agilent_82357a_register_pairlet { - short address; - unsigned short value; -}; - -enum firmware_registers { - HW_CONTROL = 0xa, - LED_CONTROL = 0xb, - RESET_TO_POWERUP = 0xc, - PROTOCOL_CONTROL = 0xd, - FAST_TALKER_T1 = 0xe -}; - -enum hardware_control_bits { - NOT_TI_RESET = 0x1, - SYSTEM_CONTROLLER = 0x2, - NOT_PARALLEL_POLL = 0x4, - OSCILLATOR_5V_ON = 0x8, - OUTPUT_5V_ON = 0x20, - CPLD_3V_ON = 0x80, -}; - -enum led_control_bits { - FIRMWARE_LED_CONTROL = 0x1, - FAIL_LED_ON = 0x20, - READY_LED_ON = 0x40, - ACCESS_LED_ON = 0x80 -}; - -enum reset_to_powerup_bits { - RESET_SPACEBALL = 0x1, // wait 2 millisec after sending -}; - -enum protocol_control_bits { - WRITE_COMPLETE_INTERRUPT_EN = 0x1, -}; - -static const int agilent_82357a_control_request = 0x4; - diff --git a/drivers/staging/gpib/cb7210/Makefile b/drivers/staging/gpib/cb7210/Makefile deleted file mode 100644 index d239ae80b415..000000000000 --- a/drivers/staging/gpib/cb7210/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_GPIB_CB7210) += cb7210.o - - diff --git a/drivers/staging/gpib/cb7210/cb7210.c b/drivers/staging/gpib/cb7210/cb7210.c deleted file mode 100644 index 3e2397898a9b..000000000000 --- a/drivers/staging/gpib/cb7210/cb7210.c +++ /dev/null @@ -1,1598 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * Measurement Computing boards using cb7210.2 and cbi488.2 chips - * copyright : (C) 2001, 2002 by Frank Mori Hess - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define DRV_NAME KBUILD_MODNAME - -#include "cb7210.h" -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <asm/dma.h> -#include <linux/bitops.h> -#include <linux/pci.h> -#include <linux/pci_ids.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/delay.h> -#include "gpib_pci_ids.h" -#include "quancom_pci.h" - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB driver Measurement Computing boards using cb7210.2 and cbi488.2"); - -static int cb7210_read(struct gpib_board *board, u8 *buffer, size_t length, - int *end, size_t *bytes_read); - - static inline int have_fifo_word(const struct cb7210_priv *cb_priv) -{ - if (((cb7210_read_byte(cb_priv, HS_STATUS)) & - (HS_RX_MSB_NOT_EMPTY | HS_RX_LSB_NOT_EMPTY)) == - (HS_RX_MSB_NOT_EMPTY | HS_RX_LSB_NOT_EMPTY)) - return 1; - else - return 0; -} - -static inline void input_fifo_enable(struct gpib_board *board, int enable) -{ - struct cb7210_priv *cb_priv = board->private_data; - struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; - unsigned long flags; - - spin_lock_irqsave(&board->spinlock, flags); - - if (enable) { - cb_priv->in_fifo_half_full = 0; - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); - - cb7210_write_byte(cb_priv, HS_RX_ENABLE | HS_TX_ENABLE | HS_CLR_SRQ_INT | - HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT | cb_priv->hs_mode_bits, - HS_MODE); - - cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK; - cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE); - - cb7210_write_byte(cb_priv, irq_bits(cb_priv->irq), HS_INT_LEVEL); - - cb_priv->hs_mode_bits |= HS_RX_ENABLE; - cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE); - } else { - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); - - cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK; - cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, nec7210_iobase(cb_priv) + - HS_MODE); - - clear_bit(READ_READY_BN, &nec_priv->state); - } - - spin_unlock_irqrestore(&board->spinlock, flags); -} - -static int fifo_read(struct gpib_board *board, struct cb7210_priv *cb_priv, u8 *buffer, - size_t length, int *end, size_t *bytes_read) -{ - ssize_t retval = 0; - struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; - int hs_status; - u16 word; - unsigned long flags; - - *bytes_read = 0; - if (cb_priv->fifo_iobase == 0) { - dev_err(board->gpib_dev, "fifo iobase is zero!\n"); - return -EIO; - } - *end = 0; - if (length <= cb7210_fifo_size) { - dev_err(board->gpib_dev, " bug! fifo read length < fifo size\n"); - return -EINVAL; - } - - input_fifo_enable(board, 1); - - while (*bytes_read + cb7210_fifo_size < length) { - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI); - - if (wait_event_interruptible(board->wait, - (cb_priv->in_fifo_half_full && - have_fifo_word(cb_priv)) || - test_bit(RECEIVED_END_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - retval = -ERESTARTSYS; - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); - break; - } - - spin_lock_irqsave(&board->spinlock, flags); - - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); - - while (have_fifo_word(cb_priv)) { - word = inw(cb_priv->fifo_iobase + DIR); - buffer[(*bytes_read)++] = word & 0xff; - buffer[(*bytes_read)++] = (word >> 8) & 0xff; - } - - cb_priv->in_fifo_half_full = 0; - - hs_status = cb7210_read_byte(cb_priv, HS_STATUS); - - spin_unlock_irqrestore(&board->spinlock, flags); - - if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state)) { - *end = 1; - break; - } - if (hs_status & HS_FIFO_FULL) - break; - if (test_bit(TIMO_NUM, &board->status)) { - retval = -ETIMEDOUT; - break; - } - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) { - retval = -EINTR; - break; - } - } - hs_status = cb7210_read_byte(cb_priv, HS_STATUS); - if (hs_status & HS_RX_LSB_NOT_EMPTY) { - word = inw(cb_priv->fifo_iobase + DIR); - buffer[(*bytes_read)++] = word & 0xff; - } - - input_fifo_enable(board, 0); - - if (wait_event_interruptible(board->wait, - test_bit(READ_READY_BN, &nec_priv->state) || - test_bit(RECEIVED_END_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - retval = -ERESTARTSYS; - } - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - if (test_bit(READ_READY_BN, &nec_priv->state)) { - nec7210_set_handshake_mode(board, nec_priv, HR_HLDA); - buffer[(*bytes_read)++] = nec7210_read_data_in(board, nec_priv, end); - } - - return retval; -} - -static int cb7210_accel_read(struct gpib_board *board, u8 *buffer, - size_t length, int *end, size_t *bytes_read) -{ - ssize_t retval; - struct cb7210_priv *cb_priv = board->private_data; - struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; - size_t num_bytes; - - *bytes_read = 0; - // deal with limitations of fifo - if (length < cb7210_fifo_size + 3 || (nec_priv->auxa_bits & HR_REOS)) - return cb7210_read(board, buffer, length, end, bytes_read); - *end = 0; - - nec7210_release_rfd_holdoff(board, nec_priv); - - if (wait_event_interruptible(board->wait, - test_bit(READ_READY_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - return -ERESTARTSYS; - } - if (test_bit(TIMO_NUM, &board->status)) - return -ETIMEDOUT; - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) - return -EINTR; - - nec7210_set_handshake_mode(board, nec_priv, HR_HLDE); - buffer[(*bytes_read)++] = nec7210_read_data_in(board, nec_priv, end); - if (*end) - return 0; - - nec7210_release_rfd_holdoff(board, nec_priv); - - retval = fifo_read(board, cb_priv, &buffer[*bytes_read], length - *bytes_read - 1, - end, &num_bytes); - *bytes_read += num_bytes; - if (retval < 0) - return retval; - if (*end) - return 0; - - retval = cb7210_read(board, &buffer[*bytes_read], 1, end, &num_bytes); - *bytes_read += num_bytes; - if (retval < 0) - return retval; - - return 0; -} - -static int output_fifo_empty(const struct cb7210_priv *cb_priv) -{ - if ((cb7210_read_byte(cb_priv, HS_STATUS) & (HS_TX_MSB_NOT_EMPTY | HS_TX_LSB_NOT_EMPTY)) - == 0) - return 1; - else - return 0; -} - -static inline void output_fifo_enable(struct gpib_board *board, int enable) -{ - struct cb7210_priv *cb_priv = board->private_data; - struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; - unsigned long flags; - - spin_lock_irqsave(&board->spinlock, flags); - - if (enable) { - nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0); - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO); - - cb7210_write_byte(cb_priv, HS_RX_ENABLE | HS_TX_ENABLE | HS_CLR_SRQ_INT | - HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT | cb_priv->hs_mode_bits, - HS_MODE); - - cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK; - cb_priv->hs_mode_bits |= HS_TX_ENABLE; - cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE); - - cb7210_write_byte(cb_priv, irq_bits(cb_priv->irq), HS_INT_LEVEL); - - clear_bit(WRITE_READY_BN, &nec_priv->state); - - } else { - cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK; - cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE); - - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0); - nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, HR_DOIE); - } - - spin_unlock_irqrestore(&board->spinlock, flags); -} - -static int fifo_write(struct gpib_board *board, u8 *buffer, size_t length, - size_t *bytes_written) -{ - size_t count = 0; - ssize_t retval = 0; - struct cb7210_priv *cb_priv = board->private_data; - struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; - unsigned int num_bytes, i; - unsigned long flags; - - *bytes_written = 0; - if (cb_priv->fifo_iobase == 0) { - dev_err(board->gpib_dev, "fifo iobase is zero!\n"); - return -EINVAL; - } - if (length == 0) - return 0; - - clear_bit(DEV_CLEAR_BN, &nec_priv->state); - clear_bit(BUS_ERROR_BN, &nec_priv->state); - - output_fifo_enable(board, 1); - - while (count < length) { - // wait until byte is ready to be sent - if (wait_event_interruptible(board->wait, - cb_priv->out_fifo_half_empty || - output_fifo_empty(cb_priv) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(BUS_ERROR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - retval = -ERESTARTSYS; - break; - } - if (test_bit(TIMO_NUM, &board->status) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(BUS_ERROR_BN, &nec_priv->state)) - break; - - if (output_fifo_empty(cb_priv)) - num_bytes = cb7210_fifo_size - cb7210_fifo_width; - else - num_bytes = cb7210_fifo_size / 2; - if (num_bytes + count > length) - num_bytes = length - count; - if (num_bytes % cb7210_fifo_width) { - dev_err(board->gpib_dev, " bug! fifo write with odd number of bytes\n"); - retval = -EINVAL; - break; - } - - spin_lock_irqsave(&board->spinlock, flags); - for (i = 0; i < num_bytes / cb7210_fifo_width; i++) { - u16 word; - - word = buffer[count++] & 0xff; - word |= (buffer[count++] << 8) & 0xff00; - outw(word, cb_priv->fifo_iobase + CDOR); - } - cb_priv->out_fifo_half_empty = 0; - cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits | - HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT, HS_MODE); - cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE); - spin_unlock_irqrestore(&board->spinlock, flags); - } - // wait last byte has been sent - if (wait_event_interruptible(board->wait, - output_fifo_empty(cb_priv) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(BUS_ERROR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - retval = -ERESTARTSYS; - } - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_bit(BUS_ERROR_BN, &nec_priv->state)) - retval = -EIO; - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - - output_fifo_enable(board, 0); - - *bytes_written = count; - return retval; -} - -static int cb7210_accel_write(struct gpib_board *board, u8 *buffer, - size_t length, int send_eoi, size_t *bytes_written) -{ - struct cb7210_priv *cb_priv = board->private_data; - struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; - unsigned long fast_chunk_size, leftover; - int retval; - size_t num_bytes; - - *bytes_written = 0; - if (length > cb7210_fifo_width) - fast_chunk_size = length - 1; - else - fast_chunk_size = 0; - fast_chunk_size -= fast_chunk_size % cb7210_fifo_width; - leftover = length - fast_chunk_size; - - retval = fifo_write(board, buffer, fast_chunk_size, &num_bytes); - *bytes_written += num_bytes; - if (retval < 0) - return retval; - - retval = nec7210_write(board, nec_priv, buffer + fast_chunk_size, leftover, - send_eoi, &num_bytes); - *bytes_written += num_bytes; - return retval; -} - -static int cb7210_line_status(const struct gpib_board *board) -{ - int status = VALID_ALL; - int bsr_bits; - struct cb7210_priv *cb_priv; - - cb_priv = board->private_data; - - bsr_bits = cb7210_paged_read_byte(cb_priv, BUS_STATUS, BUS_STATUS_PAGE); - - if ((bsr_bits & BSR_REN_BIT) == 0) - status |= BUS_REN; - if ((bsr_bits & BSR_IFC_BIT) == 0) - status |= BUS_IFC; - if ((bsr_bits & BSR_SRQ_BIT) == 0) - status |= BUS_SRQ; - if ((bsr_bits & BSR_EOI_BIT) == 0) - status |= BUS_EOI; - if ((bsr_bits & BSR_NRFD_BIT) == 0) - status |= BUS_NRFD; - if ((bsr_bits & BSR_NDAC_BIT) == 0) - status |= BUS_NDAC; - if ((bsr_bits & BSR_DAV_BIT) == 0) - status |= BUS_DAV; - if ((bsr_bits & BSR_ATN_BIT) == 0) - status |= BUS_ATN; - - return status; -} - -static int cb7210_t1_delay(struct gpib_board *board, unsigned int nano_sec) -{ - struct cb7210_priv *cb_priv = board->private_data; - struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; - unsigned int retval; - - retval = nec7210_t1_delay(board, nec_priv, nano_sec); - - if (nano_sec <= 350) { - write_byte(nec_priv, AUX_HI_SPEED, AUXMR); - retval = 350; - } else { - write_byte(nec_priv, AUX_LO_SPEED, AUXMR); - } - return retval; -} - -static irqreturn_t cb7210_locked_internal_interrupt(struct gpib_board *board); - -/* - * GPIB interrupt service routines - */ - -static irqreturn_t cb_pci_interrupt(int irq, void *arg) -{ - int bits; - struct gpib_board *board = arg; - struct cb7210_priv *priv = board->private_data; - - // first task check if this is really our interrupt in a shared irq environment - switch (priv->pci_chip) { - case PCI_CHIP_AMCC_S5933: - if ((inl(priv->amcc_iobase + INTCSR_REG) & - (INBOX_INTR_CS_BIT | INTR_ASSERTED_BIT)) == 0) - return IRQ_NONE; - - // read incoming mailbox to clear mailbox full flag - inl(priv->amcc_iobase + INCOMING_MAILBOX_REG(3)); - // clear amccs5933 interrupt - bits = INBOX_FULL_INTR_BIT | INBOX_BYTE_BITS(3) | - INBOX_SELECT_BITS(3) | INBOX_INTR_CS_BIT; - outl(bits, priv->amcc_iobase + INTCSR_REG); - break; - case PCI_CHIP_QUANCOM: - if ((inb(nec7210_iobase(priv) + QUANCOM_IRQ_CONTROL_STATUS_REG) & - QUANCOM_IRQ_ASSERTED_BIT)) - outb(QUANCOM_IRQ_ENABLE_BIT, nec7210_iobase(priv) + - QUANCOM_IRQ_CONTROL_STATUS_REG); - break; - default: - break; - } - return cb7210_locked_internal_interrupt(arg); -} - -static irqreturn_t cb7210_internal_interrupt(struct gpib_board *board) -{ - int hs_status, status1, status2; - struct cb7210_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - int clear_bits; - - if ((priv->hs_mode_bits & HS_ENABLE_MASK)) { - status1 = 0; - hs_status = cb7210_read_byte(priv, HS_STATUS); - } else { - hs_status = 0; - status1 = read_byte(nec_priv, ISR1); - } - status2 = read_byte(nec_priv, ISR2); - nec7210_interrupt_have_status(board, nec_priv, status1, status2); - - dev_dbg(board->gpib_dev, "status 0x%x, mode 0x%x\n", hs_status, priv->hs_mode_bits); - - clear_bits = 0; - - if (hs_status & HS_HALF_FULL) { - if (priv->hs_mode_bits & HS_TX_ENABLE) - priv->out_fifo_half_empty = 1; - else if (priv->hs_mode_bits & HS_RX_ENABLE) - priv->in_fifo_half_full = 1; - clear_bits |= HS_CLR_HF_INT; - } - - if (hs_status & HS_SRQ_INT) { - set_bit(SRQI_NUM, &board->status); - clear_bits |= HS_CLR_SRQ_INT; - } - - if ((hs_status & HS_EOI_INT)) { - clear_bits |= HS_CLR_EOI_EMPTY_INT; - set_bit(RECEIVED_END_BN, &nec_priv->state); - if ((nec_priv->auxa_bits & HR_HANDSHAKE_MASK) == HR_HLDE) - set_bit(RFD_HOLDOFF_BN, &nec_priv->state); - } - - if ((priv->hs_mode_bits & HS_TX_ENABLE) && - (hs_status & (HS_TX_MSB_NOT_EMPTY | HS_TX_LSB_NOT_EMPTY)) == 0) - clear_bits |= HS_CLR_EOI_EMPTY_INT; - - if (clear_bits) { - cb7210_write_byte(priv, priv->hs_mode_bits | clear_bits, HS_MODE); - cb7210_write_byte(priv, priv->hs_mode_bits, HS_MODE); - wake_up_interruptible(&board->wait); - } - - return IRQ_HANDLED; -} - -static irqreturn_t cb7210_locked_internal_interrupt(struct gpib_board *board) -{ - unsigned long flags; - irqreturn_t retval; - - spin_lock_irqsave(&board->spinlock, flags); - retval = cb7210_internal_interrupt(board); - spin_unlock_irqrestore(&board->spinlock, flags); - return retval; -} - -static irqreturn_t cb7210_interrupt(int irq, void *arg) -{ - return cb7210_internal_interrupt(arg); -} - -static int cb_pci_attach(struct gpib_board *board, const struct gpib_board_config *config); -static int cb_isa_attach(struct gpib_board *board, const struct gpib_board_config *config); - -static void cb_pci_detach(struct gpib_board *board); -static void cb_isa_detach(struct gpib_board *board); - -// wrappers for interface functions -static int cb7210_read(struct gpib_board *board, u8 *buffer, size_t length, - int *end, size_t *bytes_read) -{ - struct cb7210_priv *priv = board->private_data; - - return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); -} - -static int cb7210_write(struct gpib_board *board, u8 *buffer, size_t length, - int send_eoi, size_t *bytes_written) -{ - struct cb7210_priv *priv = board->private_data; - - return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); -} - -static int cb7210_command(struct gpib_board *board, u8 *buffer, size_t length, - size_t *bytes_written) -{ - struct cb7210_priv *priv = board->private_data; - - return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); -} - -static int cb7210_take_control(struct gpib_board *board, int synchronous) -{ - struct cb7210_priv *priv = board->private_data; - - return nec7210_take_control(board, &priv->nec7210_priv, synchronous); -} - -static int cb7210_go_to_standby(struct gpib_board *board) -{ - struct cb7210_priv *priv = board->private_data; - - return nec7210_go_to_standby(board, &priv->nec7210_priv); -} - -static int cb7210_request_system_control(struct gpib_board *board, int request_control) -{ - struct cb7210_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - - if (request_control) - priv->hs_mode_bits |= HS_SYS_CONTROL; - else - priv->hs_mode_bits &= ~HS_SYS_CONTROL; - - cb7210_write_byte(priv, priv->hs_mode_bits, HS_MODE); - return nec7210_request_system_control(board, nec_priv, request_control); -} - -static void cb7210_interface_clear(struct gpib_board *board, int assert) -{ - struct cb7210_priv *priv = board->private_data; - - nec7210_interface_clear(board, &priv->nec7210_priv, assert); -} - -static void cb7210_remote_enable(struct gpib_board *board, int enable) -{ - struct cb7210_priv *priv = board->private_data; - - nec7210_remote_enable(board, &priv->nec7210_priv, enable); -} - -static int cb7210_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits) -{ - struct cb7210_priv *priv = board->private_data; - - return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); -} - -static void cb7210_disable_eos(struct gpib_board *board) -{ - struct cb7210_priv *priv = board->private_data; - - nec7210_disable_eos(board, &priv->nec7210_priv); -} - -static unsigned int cb7210_update_status(struct gpib_board *board, unsigned int clear_mask) -{ - struct cb7210_priv *priv = board->private_data; - - return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); -} - -static int cb7210_primary_address(struct gpib_board *board, unsigned int address) -{ - struct cb7210_priv *priv = board->private_data; - - return nec7210_primary_address(board, &priv->nec7210_priv, address); -} - -static int cb7210_secondary_address(struct gpib_board *board, unsigned int address, int enable) -{ - struct cb7210_priv *priv = board->private_data; - - return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); -} - -static int cb7210_parallel_poll(struct gpib_board *board, u8 *result) -{ - struct cb7210_priv *priv = board->private_data; - - return nec7210_parallel_poll(board, &priv->nec7210_priv, result); -} - -static void cb7210_parallel_poll_configure(struct gpib_board *board, u8 configuration) -{ - struct cb7210_priv *priv = board->private_data; - - nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration); -} - -static void cb7210_parallel_poll_response(struct gpib_board *board, int ist) -{ - struct cb7210_priv *priv = board->private_data; - - nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); -} - -static void cb7210_serial_poll_response(struct gpib_board *board, u8 status) -{ - struct cb7210_priv *priv = board->private_data; - - nec7210_serial_poll_response(board, &priv->nec7210_priv, status); -} - -static u8 cb7210_serial_poll_status(struct gpib_board *board) -{ - struct cb7210_priv *priv = board->private_data; - - return nec7210_serial_poll_status(board, &priv->nec7210_priv); -} - -static void cb7210_return_to_local(struct gpib_board *board) -{ - struct cb7210_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - - write_byte(nec_priv, AUX_RTL2, AUXMR); - udelay(1); - write_byte(nec_priv, AUX_RTL, AUXMR); -} - -static struct gpib_interface cb_pci_unaccel_interface = { - .name = "cbi_pci_unaccel", - .attach = cb_pci_attach, - .detach = cb_pci_detach, - .read = cb7210_read, - .write = cb7210_write, - .command = cb7210_command, - .take_control = cb7210_take_control, - .go_to_standby = cb7210_go_to_standby, - .request_system_control = cb7210_request_system_control, - .interface_clear = cb7210_interface_clear, - .remote_enable = cb7210_remote_enable, - .enable_eos = cb7210_enable_eos, - .disable_eos = cb7210_disable_eos, - .parallel_poll = cb7210_parallel_poll, - .parallel_poll_configure = cb7210_parallel_poll_configure, - .parallel_poll_response = cb7210_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = cb7210_line_status, - .update_status = cb7210_update_status, - .primary_address = cb7210_primary_address, - .secondary_address = cb7210_secondary_address, - .serial_poll_response = cb7210_serial_poll_response, - .serial_poll_status = cb7210_serial_poll_status, - .t1_delay = cb7210_t1_delay, - .return_to_local = cb7210_return_to_local, -}; - -static struct gpib_interface cb_pci_accel_interface = { - .name = "cbi_pci_accel", - .attach = cb_pci_attach, - .detach = cb_pci_detach, - .read = cb7210_accel_read, - .write = cb7210_accel_write, - .command = cb7210_command, - .take_control = cb7210_take_control, - .go_to_standby = cb7210_go_to_standby, - .request_system_control = cb7210_request_system_control, - .interface_clear = cb7210_interface_clear, - .remote_enable = cb7210_remote_enable, - .enable_eos = cb7210_enable_eos, - .disable_eos = cb7210_disable_eos, - .parallel_poll = cb7210_parallel_poll, - .parallel_poll_configure = cb7210_parallel_poll_configure, - .parallel_poll_response = cb7210_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = cb7210_line_status, - .update_status = cb7210_update_status, - .primary_address = cb7210_primary_address, - .secondary_address = cb7210_secondary_address, - .serial_poll_response = cb7210_serial_poll_response, - .serial_poll_status = cb7210_serial_poll_status, - .t1_delay = cb7210_t1_delay, - .return_to_local = cb7210_return_to_local, -}; - -static struct gpib_interface cb_pci_interface = { - .name = "cbi_pci", - .attach = cb_pci_attach, - .detach = cb_pci_detach, - .read = cb7210_accel_read, - .write = cb7210_accel_write, - .command = cb7210_command, - .take_control = cb7210_take_control, - .go_to_standby = cb7210_go_to_standby, - .request_system_control = cb7210_request_system_control, - .interface_clear = cb7210_interface_clear, - .remote_enable = cb7210_remote_enable, - .enable_eos = cb7210_enable_eos, - .disable_eos = cb7210_disable_eos, - .parallel_poll = cb7210_parallel_poll, - .parallel_poll_configure = cb7210_parallel_poll_configure, - .parallel_poll_response = cb7210_parallel_poll_response, - .line_status = cb7210_line_status, - .update_status = cb7210_update_status, - .primary_address = cb7210_primary_address, - .secondary_address = cb7210_secondary_address, - .serial_poll_response = cb7210_serial_poll_response, - .serial_poll_status = cb7210_serial_poll_status, - .t1_delay = cb7210_t1_delay, - .return_to_local = cb7210_return_to_local, -}; - -static struct gpib_interface cb_isa_unaccel_interface = { - .name = "cbi_isa_unaccel", - .attach = cb_isa_attach, - .detach = cb_isa_detach, - .read = cb7210_read, - .write = cb7210_write, - .command = cb7210_command, - .take_control = cb7210_take_control, - .go_to_standby = cb7210_go_to_standby, - .request_system_control = cb7210_request_system_control, - .interface_clear = cb7210_interface_clear, - .remote_enable = cb7210_remote_enable, - .enable_eos = cb7210_enable_eos, - .disable_eos = cb7210_disable_eos, - .parallel_poll = cb7210_parallel_poll, - .parallel_poll_configure = cb7210_parallel_poll_configure, - .parallel_poll_response = cb7210_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = cb7210_line_status, - .update_status = cb7210_update_status, - .primary_address = cb7210_primary_address, - .secondary_address = cb7210_secondary_address, - .serial_poll_response = cb7210_serial_poll_response, - .serial_poll_status = cb7210_serial_poll_status, - .t1_delay = cb7210_t1_delay, - .return_to_local = cb7210_return_to_local, -}; - -static struct gpib_interface cb_isa_interface = { - .name = "cbi_isa", - .attach = cb_isa_attach, - .detach = cb_isa_detach, - .read = cb7210_accel_read, - .write = cb7210_accel_write, - .command = cb7210_command, - .take_control = cb7210_take_control, - .go_to_standby = cb7210_go_to_standby, - .request_system_control = cb7210_request_system_control, - .interface_clear = cb7210_interface_clear, - .remote_enable = cb7210_remote_enable, - .enable_eos = cb7210_enable_eos, - .disable_eos = cb7210_disable_eos, - .parallel_poll = cb7210_parallel_poll, - .parallel_poll_configure = cb7210_parallel_poll_configure, - .parallel_poll_response = cb7210_parallel_poll_response, - .line_status = cb7210_line_status, - .update_status = cb7210_update_status, - .primary_address = cb7210_primary_address, - .secondary_address = cb7210_secondary_address, - .serial_poll_response = cb7210_serial_poll_response, - .serial_poll_status = cb7210_serial_poll_status, - .t1_delay = cb7210_t1_delay, - .return_to_local = cb7210_return_to_local, -}; - -static struct gpib_interface cb_isa_accel_interface = { - .name = "cbi_isa_accel", - .attach = cb_isa_attach, - .detach = cb_isa_detach, - .read = cb7210_accel_read, - .write = cb7210_accel_write, - .command = cb7210_command, - .take_control = cb7210_take_control, - .go_to_standby = cb7210_go_to_standby, - .request_system_control = cb7210_request_system_control, - .interface_clear = cb7210_interface_clear, - .remote_enable = cb7210_remote_enable, - .enable_eos = cb7210_enable_eos, - .disable_eos = cb7210_disable_eos, - .parallel_poll = cb7210_parallel_poll, - .parallel_poll_configure = cb7210_parallel_poll_configure, - .parallel_poll_response = cb7210_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = cb7210_line_status, - .update_status = cb7210_update_status, - .primary_address = cb7210_primary_address, - .secondary_address = cb7210_secondary_address, - .serial_poll_response = cb7210_serial_poll_response, - .serial_poll_status = cb7210_serial_poll_status, - .t1_delay = cb7210_t1_delay, - .return_to_local = cb7210_return_to_local, -}; - -static int cb7210_allocate_private(struct gpib_board *board) -{ - struct cb7210_priv *priv; - - board->private_data = kmalloc(sizeof(struct cb7210_priv), GFP_KERNEL); - if (!board->private_data) - return -ENOMEM; - priv = board->private_data; - memset(priv, 0, sizeof(struct cb7210_priv)); - init_nec7210_private(&priv->nec7210_priv); - return 0; -} - -static void cb7210_generic_detach(struct gpib_board *board) -{ - kfree(board->private_data); - board->private_data = NULL; -} - -// generic part of attach functions shared by all cb7210 boards -static int cb7210_generic_attach(struct gpib_board *board) -{ - struct cb7210_priv *cb_priv; - struct nec7210_priv *nec_priv; - - board->status = 0; - - if (cb7210_allocate_private(board)) - return -ENOMEM; - cb_priv = board->private_data; - nec_priv = &cb_priv->nec7210_priv; - nec_priv->read_byte = nec7210_locking_ioport_read_byte; - nec_priv->write_byte = nec7210_locking_ioport_write_byte; - nec_priv->offset = cb7210_reg_offset; - nec_priv->type = CB7210; - return 0; -} - -static int cb7210_init(struct cb7210_priv *cb_priv, struct gpib_board *board) -{ - struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; - - cb7210_write_byte(cb_priv, HS_RESET7210, HS_INT_LEVEL); - cb7210_write_byte(cb_priv, irq_bits(cb_priv->irq), HS_INT_LEVEL); - - nec7210_board_reset(nec_priv, board); - cb7210_write_byte(cb_priv, HS_TX_ENABLE | HS_RX_ENABLE | HS_CLR_SRQ_INT | - HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT, HS_MODE); - - cb_priv->hs_mode_bits = HS_HF_INT_EN; - cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE); - - write_byte(nec_priv, AUX_LO_SPEED, AUXMR); - /* - * set clock register for maximum (20 MHz) driving frequency - * ICR should be set to clock in megahertz (1-15) and to zero - * for clocks faster than 15 MHz (max 20MHz) - */ - write_byte(nec_priv, ICR | 0, AUXMR); - - if (cb_priv->pci_chip == PCI_CHIP_QUANCOM) { - /* change interrupt polarity */ - nec_priv->auxb_bits |= HR_INV; - write_byte(nec_priv, nec_priv->auxb_bits, AUXMR); - } - nec7210_board_online(nec_priv, board); - - /* poll so we can detect assertion of ATN */ - if (gpib_request_pseudo_irq(board, cb_pci_interrupt)) { - pr_err("failed to allocate pseudo_irq\n"); - return -1; - } - return 0; -} - -static int cb_pci_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct cb7210_priv *cb_priv; - struct nec7210_priv *nec_priv; - int isr_flags = 0; - int bits; - int retval; - - retval = cb7210_generic_attach(board); - if (retval) - return retval; - - cb_priv = board->private_data; - nec_priv = &cb_priv->nec7210_priv; - - cb_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_CBOARDS, - PCI_DEVICE_ID_CBOARDS_PCI_GPIB, NULL); - if (cb_priv->pci_device) - cb_priv->pci_chip = PCI_CHIP_AMCC_S5933; - if (!cb_priv->pci_device) { - cb_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_CBOARDS, - PCI_DEVICE_ID_CBOARDS_CPCI_GPIB, NULL); - if (cb_priv->pci_device) - cb_priv->pci_chip = PCI_CHIP_AMCC_S5933; - } - if (!cb_priv->pci_device) { - cb_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_QUANCOM, - PCI_DEVICE_ID_QUANCOM_GPIB, NULL); - if (cb_priv->pci_device) { - cb_priv->pci_chip = PCI_CHIP_QUANCOM; - nec_priv->offset = 4; - } - } - if (!cb_priv->pci_device) { - dev_err(board->gpib_dev, "no supported boards found.\n"); - return -ENODEV; - } - - if (pci_enable_device(cb_priv->pci_device)) { - dev_err(board->gpib_dev, "error enabling pci device\n"); - return -EIO; - } - - if (pci_request_regions(cb_priv->pci_device, DRV_NAME)) - return -EBUSY; - switch (cb_priv->pci_chip) { - case PCI_CHIP_AMCC_S5933: - cb_priv->amcc_iobase = pci_resource_start(cb_priv->pci_device, 0); - nec_priv->iobase = pci_resource_start(cb_priv->pci_device, 1); - cb_priv->fifo_iobase = pci_resource_start(cb_priv->pci_device, 2); - break; - case PCI_CHIP_QUANCOM: - nec_priv->iobase = pci_resource_start(cb_priv->pci_device, 0); - cb_priv->fifo_iobase = nec_priv->iobase; - break; - default: - dev_err(board->gpib_dev, "bug! unhandled pci_chip=%i\n", cb_priv->pci_chip); - return -EIO; - } - isr_flags |= IRQF_SHARED; - if (request_irq(cb_priv->pci_device->irq, cb_pci_interrupt, isr_flags, DRV_NAME, board)) { - dev_err(board->gpib_dev, "can't request IRQ %d\n", - cb_priv->pci_device->irq); - return -EBUSY; - } - cb_priv->irq = cb_priv->pci_device->irq; - - switch (cb_priv->pci_chip) { - case PCI_CHIP_AMCC_S5933: - // make sure mailbox flags are clear - inl(cb_priv->amcc_iobase + INCOMING_MAILBOX_REG(3)); - // enable interrupts on amccs5933 chip - bits = INBOX_FULL_INTR_BIT | INBOX_BYTE_BITS(3) | INBOX_SELECT_BITS(3) | - INBOX_INTR_CS_BIT; - outl(bits, cb_priv->amcc_iobase + INTCSR_REG); - break; - default: - break; - } - return cb7210_init(cb_priv, board); -} - -static void cb_pci_detach(struct gpib_board *board) -{ - struct cb7210_priv *cb_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (cb_priv) { - gpib_free_pseudo_irq(board); - nec_priv = &cb_priv->nec7210_priv; - if (cb_priv->irq) { - // disable amcc interrupts - outl(0, cb_priv->amcc_iobase + INTCSR_REG); - free_irq(cb_priv->irq, board); - } - if (nec_priv->iobase) { - nec7210_board_reset(nec_priv, board); - pci_release_regions(cb_priv->pci_device); - } - if (cb_priv->pci_device) - pci_dev_put(cb_priv->pci_device); - } - cb7210_generic_detach(board); -} - -static int cb_isa_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - int isr_flags = 0; - struct cb7210_priv *cb_priv; - struct nec7210_priv *nec_priv; - unsigned int bits; - int retval; - - retval = cb7210_generic_attach(board); - if (retval) - return retval; - cb_priv = board->private_data; - nec_priv = &cb_priv->nec7210_priv; - if (!request_region(config->ibbase, cb7210_iosize, DRV_NAME)) { - dev_err(board->gpib_dev, "ioports starting at 0x%x are already in use\n", - config->ibbase); - return -EBUSY; - } - nec_priv->iobase = config->ibbase; - cb_priv->fifo_iobase = nec7210_iobase(cb_priv); - - bits = irq_bits(config->ibirq); - if (bits == 0) - dev_err(board->gpib_dev, "board incapable of using irq %i, try 2-5, 7, 10, or 11\n", - config->ibirq); - - // install interrupt handler - if (request_irq(config->ibirq, cb7210_interrupt, isr_flags, DRV_NAME, board)) { - dev_err(board->gpib_dev, "failed to obtain IRQ %d\n", config->ibirq); - return -EBUSY; - } - cb_priv->irq = config->ibirq; - - return cb7210_init(cb_priv, board); -} - -static void cb_isa_detach(struct gpib_board *board) -{ - struct cb7210_priv *cb_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (cb_priv) { - gpib_free_pseudo_irq(board); - nec_priv = &cb_priv->nec7210_priv; - if (cb_priv->irq) - free_irq(cb_priv->irq, board); - if (nec_priv->iobase) { - nec7210_board_reset(nec_priv, board); - release_region(nec7210_iobase(cb_priv), cb7210_iosize); - } - } - cb7210_generic_detach(board); -} - -static int cb7210_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - return 0; -} - -static const struct pci_device_id cb7210_pci_table[] = { - {PCI_VENDOR_ID_CBOARDS, PCI_DEVICE_ID_CBOARDS_PCI_GPIB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - {PCI_VENDOR_ID_CBOARDS, PCI_DEVICE_ID_CBOARDS_CPCI_GPIB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - {PCI_VENDOR_ID_QUANCOM, PCI_DEVICE_ID_QUANCOM_GPIB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, cb7210_pci_table); - -static struct pci_driver cb7210_pci_driver = { - .name = DRV_NAME, - .id_table = cb7210_pci_table, - .probe = &cb7210_pci_probe -}; - -/*************************************************************************** - * Support for computer boards pcmcia-gpib card - * - * Based on gpib PCMCIA client driver written by Claus Schroeter - * (clausi@chemie.fu-berlin.de), which was adapted from the - * pcmcia skeleton example (presumably David Hinds) - ***************************************************************************/ - -#ifdef CONFIG_GPIB_PCMCIA - -#include <linux/kernel.h> -#include <linux/ptrace.h> -#include <linux/timer.h> -#include <linux/io.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/ds.h> - -/* - * The event() function is this driver's Card Services event handler. - * It will be called by Card Services when an appropriate card status - * event is received. The config() and release() entry points are - * used to configure or release a socket, in response to card insertion - * and ejection events. They are invoked from the gpib event - * handler. - */ - -static int cb_gpib_config(struct pcmcia_device *link); -static void cb_gpib_release(struct pcmcia_device *link); -static int cb_pcmcia_attach(struct gpib_board *board, const struct gpib_board_config *config); -static void cb_pcmcia_detach(struct gpib_board *board); - -/* - * A linked list of "instances" of the gpib device. Each actual - * PCMCIA card corresponds to one device instance, and is described - * by one dev_link_t structure (defined in ds.h). - * - * You may not want to use a linked list for this -- for example, the - * memory card driver uses an array of dev_link_t pointers, where minor - * device numbers are used to derive the corresponding array index. - */ - -static struct pcmcia_device *curr_dev; - -/* - * A dev_link_t structure has fields for most things that are needed - * to keep track of a socket, but there will usually be some device - * specific information that also needs to be kept track of. The - * 'priv' pointer in a dev_link_t structure can be used to point to - * a device-specific private data structure, like this. - * - * A driver needs to provide a dev_node_t structure for each device - * on a card. In some cases, there is only one device per card (for - * example, ethernet cards, modems). In other cases, there may be - * many actual or logical devices (SCSI adapters, memory cards with - * multiple partitions). The dev_node_t structures need to be kept - * in a linked list starting at the 'dev' field of a dev_link_t - * structure. We allocate them in the card's private data structure, - * because they generally can't be allocated dynamically. - */ - -struct local_info { - struct pcmcia_device *p_dev; - struct gpib_board *dev; -}; - -/* - * gpib_attach() creates an "instance" of the driver, allocating - * local data structures for one device. The device is registered - * with Card Services. - * - * The dev_link structure is initialized, but we don't actually - * configure the card at this point -- we wait until we receive a - * card insertion event. - */ - -static int cb_gpib_probe(struct pcmcia_device *link) -{ - struct local_info *info; - int ret; - - /* Allocate space for private device-specific data */ - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - info->p_dev = link; - link->priv = info; - - /* The io structure describes IO port mapping */ - link->resource[0]->end = 16; - link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; - link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; - link->resource[1]->end = 16; - link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; - link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16; - link->io_lines = 10; - - /* General socket configuration */ - link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - link->config_index = 1; - link->config_regs = PRESENT_OPTION; - - /* Register with Card Services */ - curr_dev = link; - ret = cb_gpib_config(link); - if (ret) - goto free_info; - - return 0; - -free_info: - kfree(info); - return ret; -} - -/* - * This deletes a driver "instance". The device is de-registered - * with Card Services. If it has been released, all local data - * structures are freed. Otherwise, the structures will be freed - * when the device is released. - */ - -static void cb_gpib_remove(struct pcmcia_device *link) -{ - struct local_info *info = link->priv; - //struct struct gpib_board *dev = info->dev; - - if (info->dev) - cb_pcmcia_detach(info->dev); - cb_gpib_release(link); - - //free_netdev(dev); - kfree(info); -} - -static int cb_gpib_config_iteration(struct pcmcia_device *link, void *priv_data) -{ - return pcmcia_request_io(link); -} - -/* - * gpib_config() is scheduled to run after a CARD_INSERTION event - * is received, to configure the PCMCIA socket, and to make the - * ethernet device available to the system. - */ - -static int cb_gpib_config(struct pcmcia_device *link) -{ - int retval; - - retval = pcmcia_loop_config(link, &cb_gpib_config_iteration, NULL); - if (retval) { - dev_warn(&link->dev, "no configuration found\n"); - cb_gpib_release(link); - return -ENODEV; - } - - /* - * This actually configures the PCMCIA socket -- setting up - * the I/O windows and the interrupt mapping. - */ - retval = pcmcia_enable_device(link); - if (retval) { - dev_warn(&link->dev, "pcmcia_enable_device failed\n"); - cb_gpib_release(link); - return -ENODEV; - } - - return 0; -} /* gpib_config */ - -/* - * After a card is removed, gpib_release() will unregister the net - * device, and release the PCMCIA configuration. If the device is - * still open, this will be postponed until it is closed. - */ - -static void cb_gpib_release(struct pcmcia_device *link) -{ - pcmcia_disable_device(link); -} - -static int cb_gpib_suspend(struct pcmcia_device *link) -{ - //struct local_info *info = link->priv; - //struct struct gpib_board *dev = info->dev; - - if (link->open) - dev_warn(&link->dev, "Device still open\n"); - //netif_device_detach(dev); - - return 0; -} - -static int cb_gpib_resume(struct pcmcia_device *link) -{ - //struct local_info *info = link->priv; - //struct struct gpib_board *dev = info->dev; - - /*if (link->open) { - * ni_gpib_probe(dev); / really? - * //netif_device_attach(dev); - * - */ - return cb_gpib_config(link); -} - -/*====================================================================*/ - -static struct pcmcia_device_id cb_pcmcia_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0005), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, cb_pcmcia_ids); - -static struct pcmcia_driver cb_gpib_cs_driver = { - .name = "cb_gpib_cs", - .owner = THIS_MODULE, - .id_table = cb_pcmcia_ids, - .probe = cb_gpib_probe, - .remove = cb_gpib_remove, - .suspend = cb_gpib_suspend, - .resume = cb_gpib_resume, -}; - -static void cb_pcmcia_cleanup_module(void) -{ - pcmcia_unregister_driver(&cb_gpib_cs_driver); -} - -static struct gpib_interface cb_pcmcia_unaccel_interface = { - .name = "cbi_pcmcia_unaccel", - .attach = cb_pcmcia_attach, - .detach = cb_pcmcia_detach, - .read = cb7210_read, - .write = cb7210_write, - .command = cb7210_command, - .take_control = cb7210_take_control, - .go_to_standby = cb7210_go_to_standby, - .request_system_control = cb7210_request_system_control, - .interface_clear = cb7210_interface_clear, - .remote_enable = cb7210_remote_enable, - .enable_eos = cb7210_enable_eos, - .disable_eos = cb7210_disable_eos, - .parallel_poll = cb7210_parallel_poll, - .parallel_poll_configure = cb7210_parallel_poll_configure, - .parallel_poll_response = cb7210_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = cb7210_line_status, - .update_status = cb7210_update_status, - .primary_address = cb7210_primary_address, - .secondary_address = cb7210_secondary_address, - .serial_poll_response = cb7210_serial_poll_response, - .serial_poll_status = cb7210_serial_poll_status, - .t1_delay = cb7210_t1_delay, - .return_to_local = cb7210_return_to_local, -}; - -static struct gpib_interface cb_pcmcia_interface = { - .name = "cbi_pcmcia", - .attach = cb_pcmcia_attach, - .detach = cb_pcmcia_detach, - .read = cb7210_accel_read, - .write = cb7210_accel_write, - .command = cb7210_command, - .take_control = cb7210_take_control, - .go_to_standby = cb7210_go_to_standby, - .request_system_control = cb7210_request_system_control, - .interface_clear = cb7210_interface_clear, - .remote_enable = cb7210_remote_enable, - .enable_eos = cb7210_enable_eos, - .disable_eos = cb7210_disable_eos, - .parallel_poll = cb7210_parallel_poll, - .parallel_poll_configure = cb7210_parallel_poll_configure, - .parallel_poll_response = cb7210_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = cb7210_line_status, - .update_status = cb7210_update_status, - .primary_address = cb7210_primary_address, - .secondary_address = cb7210_secondary_address, - .serial_poll_response = cb7210_serial_poll_response, - .serial_poll_status = cb7210_serial_poll_status, - .t1_delay = cb7210_t1_delay, - .return_to_local = cb7210_return_to_local, -}; - -static struct gpib_interface cb_pcmcia_accel_interface = { - .name = "cbi_pcmcia_accel", - .attach = cb_pcmcia_attach, - .detach = cb_pcmcia_detach, - .read = cb7210_accel_read, - .write = cb7210_accel_write, - .command = cb7210_command, - .take_control = cb7210_take_control, - .go_to_standby = cb7210_go_to_standby, - .request_system_control = cb7210_request_system_control, - .interface_clear = cb7210_interface_clear, - .remote_enable = cb7210_remote_enable, - .enable_eos = cb7210_enable_eos, - .disable_eos = cb7210_disable_eos, - .parallel_poll = cb7210_parallel_poll, - .parallel_poll_configure = cb7210_parallel_poll_configure, - .parallel_poll_response = cb7210_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = cb7210_line_status, - .update_status = cb7210_update_status, - .primary_address = cb7210_primary_address, - .secondary_address = cb7210_secondary_address, - .serial_poll_response = cb7210_serial_poll_response, - .serial_poll_status = cb7210_serial_poll_status, - .t1_delay = cb7210_t1_delay, - .return_to_local = cb7210_return_to_local, -}; - -static int cb_pcmcia_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct cb7210_priv *cb_priv; - struct nec7210_priv *nec_priv; - int retval; - - if (!curr_dev) { - dev_err(board->gpib_dev, "no cb pcmcia cards found\n"); - return -ENODEV; - } - - retval = cb7210_generic_attach(board); - if (retval) - return retval; - - cb_priv = board->private_data; - nec_priv = &cb_priv->nec7210_priv; - - if (!request_region(curr_dev->resource[0]->start, resource_size(curr_dev->resource[0]), - DRV_NAME)) { - dev_err(board->gpib_dev, "ioports starting at 0x%lx are already in use\n", - (unsigned long)curr_dev->resource[0]->start); - return -EBUSY; - } - nec_priv->iobase = curr_dev->resource[0]->start; - cb_priv->fifo_iobase = curr_dev->resource[0]->start; - - if (request_irq(curr_dev->irq, cb7210_interrupt, IRQF_SHARED, DRV_NAME, board)) { - dev_err(board->gpib_dev, "failed to request IRQ %d\n", curr_dev->irq); - return -EBUSY; - } - cb_priv->irq = curr_dev->irq; - - return cb7210_init(cb_priv, board); -} - -static void cb_pcmcia_detach(struct gpib_board *board) -{ - struct cb7210_priv *cb_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (cb_priv) { - nec_priv = &cb_priv->nec7210_priv; - gpib_free_pseudo_irq(board); - if (cb_priv->irq) - free_irq(cb_priv->irq, board); - if (nec_priv->iobase) { - nec7210_board_reset(nec_priv, board); - release_region(nec7210_iobase(cb_priv), cb7210_iosize); - } - } - cb7210_generic_detach(board); -} - -#endif /* CONFIG_GPIB_PCMCIA */ - -static int __init cb7210_init_module(void) -{ - int ret; - - ret = pci_register_driver(&cb7210_pci_driver); - if (ret) { - pr_err("pci_register_driver failed: error = %d\n", ret); - return ret; - } - - ret = gpib_register_driver(&cb_pci_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pci; - } - - ret = gpib_register_driver(&cb_isa_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_isa; - } - - ret = gpib_register_driver(&cb_pci_accel_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pci_accel; - } - - ret = gpib_register_driver(&cb_pci_unaccel_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pci_unaccel; - } - - ret = gpib_register_driver(&cb_isa_accel_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_isa_accel; - } - - ret = gpib_register_driver(&cb_isa_unaccel_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_isa_unaccel; - } - -#ifdef CONFIG_GPIB_PCMCIA - ret = gpib_register_driver(&cb_pcmcia_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pcmcia; - } - - ret = gpib_register_driver(&cb_pcmcia_accel_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pcmcia_accel; - } - - ret = gpib_register_driver(&cb_pcmcia_unaccel_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pcmcia_unaccel; - } - - ret = pcmcia_register_driver(&cb_gpib_cs_driver); - if (ret) { - pr_err("pcmcia_register_driver failed: error = %d\n", ret); - goto err_pcmcia_driver; - } -#endif - - return 0; - -#ifdef CONFIG_GPIB_PCMCIA -err_pcmcia_driver: - gpib_unregister_driver(&cb_pcmcia_unaccel_interface); -err_pcmcia_unaccel: - gpib_unregister_driver(&cb_pcmcia_accel_interface); -err_pcmcia_accel: - gpib_unregister_driver(&cb_pcmcia_interface); -err_pcmcia: -#endif - gpib_unregister_driver(&cb_isa_unaccel_interface); -err_isa_unaccel: - gpib_unregister_driver(&cb_isa_accel_interface); -err_isa_accel: - gpib_unregister_driver(&cb_pci_unaccel_interface); -err_pci_unaccel: - gpib_unregister_driver(&cb_pci_accel_interface); -err_pci_accel: - gpib_unregister_driver(&cb_isa_interface); -err_isa: - gpib_unregister_driver(&cb_pci_interface); -err_pci: - pci_unregister_driver(&cb7210_pci_driver); - - return ret; -} - -static void __exit cb7210_exit_module(void) -{ - gpib_unregister_driver(&cb_pci_interface); - gpib_unregister_driver(&cb_isa_interface); - gpib_unregister_driver(&cb_pci_accel_interface); - gpib_unregister_driver(&cb_pci_unaccel_interface); - gpib_unregister_driver(&cb_isa_accel_interface); - gpib_unregister_driver(&cb_isa_unaccel_interface); -#ifdef CONFIG_GPIB_PCMCIA - gpib_unregister_driver(&cb_pcmcia_interface); - gpib_unregister_driver(&cb_pcmcia_accel_interface); - gpib_unregister_driver(&cb_pcmcia_unaccel_interface); - cb_pcmcia_cleanup_module(); -#endif - - pci_unregister_driver(&cb7210_pci_driver); -} - -module_init(cb7210_init_module); -module_exit(cb7210_exit_module); diff --git a/drivers/staging/gpib/cb7210/cb7210.h b/drivers/staging/gpib/cb7210/cb7210.h deleted file mode 100644 index ddc841ff87ae..000000000000 --- a/drivers/staging/gpib/cb7210/cb7210.h +++ /dev/null @@ -1,203 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -#include "nec7210.h" -#include "gpibP.h" -#include "amccs5933.h" - -#include <linux/delay.h> -#include <linux/interrupt.h> - -enum { - PCI_DEVICE_ID_CBOARDS_PCI_GPIB = 0x6, - PCI_DEVICE_ID_CBOARDS_CPCI_GPIB = 0xe, -}; - -enum pci_chip { - PCI_CHIP_NONE = 0, - PCI_CHIP_AMCC_S5933, - PCI_CHIP_QUANCOM -}; - -// struct which defines private_data for cb7210 boards -struct cb7210_priv { - struct nec7210_priv nec7210_priv; - struct pci_dev *pci_device; - // base address of amccs5933 pci chip - unsigned long amcc_iobase; - unsigned long fifo_iobase; - unsigned int irq; - enum pci_chip pci_chip; - u8 hs_mode_bits; - unsigned out_fifo_half_empty : 1; - unsigned in_fifo_half_full : 1; -}; - -// pci-gpib register offset -static const int cb7210_reg_offset = 1; - -// uses 10 ioports -static const int cb7210_iosize = 10; - -// fifo size in bytes -static const int cb7210_fifo_size = 2048; -static const int cb7210_fifo_width = 2; - -// cb7210 specific registers and bits -enum cb7210_regs { - BUS_STATUS = 0x7, -}; - -enum cb7210_page_in { - BUS_STATUS_PAGE = 1, -}; - -enum hs_regs { - // write registers - HS_MODE = 0x8, /* HS_MODE register */ - HS_INT_LEVEL = 0x9, /* HS_INT_LEVEL register */ - // read registers - HS_STATUS = 0x8, /* HS_STATUS register */ -}; - -static inline u32 nec7210_iobase(const struct cb7210_priv *cb_priv) -{ - return cb_priv->nec7210_priv.iobase; -} - -static inline int cb7210_page_in_bits(unsigned int page) -{ - return 0x50 | (page & 0xf); -} - -static inline u8 cb7210_paged_read_byte(struct cb7210_priv *cb_priv, - unsigned int register_num, unsigned int page) -{ - struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; - u8 retval; - unsigned long flags; - - spin_lock_irqsave(&nec_priv->register_page_lock, flags); - outb(cb7210_page_in_bits(page), nec7210_iobase(cb_priv) + AUXMR * nec_priv->offset); - udelay(1); - retval = inb(nec7210_iobase(cb_priv) + register_num * nec_priv->offset); - spin_unlock_irqrestore(&nec_priv->register_page_lock, flags); - return retval; -} - -// don't use for register_num < 8, since it doesn't lock -static inline u8 cb7210_read_byte(const struct cb7210_priv *cb_priv, - enum hs_regs register_num) -{ - const struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; - u8 retval; - - retval = inb(nec7210_iobase(cb_priv) + register_num * nec_priv->offset); - return retval; -} - -static inline void cb7210_paged_write_byte(struct cb7210_priv *cb_priv, u8 data, - unsigned int register_num, unsigned int page) -{ - struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; - unsigned long flags; - - spin_lock_irqsave(&nec_priv->register_page_lock, flags); - outb(cb7210_page_in_bits(page), nec7210_iobase(cb_priv) + AUXMR * nec_priv->offset); - udelay(1); - outb(data, nec7210_iobase(cb_priv) + register_num * nec_priv->offset); - spin_unlock_irqrestore(&nec_priv->register_page_lock, flags); -} - -// don't use for register_num < 8, since it doesn't lock -static inline void cb7210_write_byte(const struct cb7210_priv *cb_priv, u8 data, - enum hs_regs register_num) -{ - const struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv; - - outb(data, nec7210_iobase(cb_priv) + register_num * nec_priv->offset); -} - -enum bus_status_bits { - BSR_ATN_BIT = 0x1, - BSR_EOI_BIT = 0x2, - BSR_SRQ_BIT = 0x4, - BSR_IFC_BIT = 0x8, - BSR_REN_BIT = 0x10, - BSR_DAV_BIT = 0x20, - BSR_NRFD_BIT = 0x40, - BSR_NDAC_BIT = 0x80, -}; - -/* CBI 488.2 HS control */ - -/* - * when both bit 0 and 1 are set, it - * 1 clears the transmit state machine to an initial condition - * 2 clears any residual interrupts left latched on cbi488.2 - * 3 resets all control bits in HS_MODE to zero - * 4 enables TX empty interrupts - * when both bit 0 and 1 are zero, then the high speed mode is disabled - */ -enum hs_mode_bits { - HS_ENABLE_MASK = 0x3, - HS_TX_ENABLE = (1 << 0), - HS_RX_ENABLE = (1 << 1), - HS_HF_INT_EN = (1 << 3), - HS_CLR_SRQ_INT = (1 << 4), - HS_CLR_EOI_EMPTY_INT = (1 << 5), - HS_CLR_HF_INT = (1 << 6), - HS_SYS_CONTROL = (1 << 7), -}; - -/* CBI 488.2 status */ -enum hs_status_bits { - HS_FIFO_FULL = (1 << 0), - HS_HALF_FULL = (1 << 1), - HS_SRQ_INT = (1 << 2), - HS_EOI_INT = (1 << 3), - HS_TX_MSB_NOT_EMPTY = (1 << 4), - HS_RX_MSB_NOT_EMPTY = (1 << 5), - HS_TX_LSB_NOT_EMPTY = (1 << 6), - HS_RX_LSB_NOT_EMPTY = (1 << 7), -}; - -/* CBI488.2 hs_int_level register */ -enum hs_int_level_bits { - HS_RESET7210 = (1 << 7), -}; - -static inline unsigned int irq_bits(unsigned int irq) -{ - switch (irq) { - case 2: - case 3: - case 4: - case 5: - return irq - 1; - case 7: - return 0x5; - case 10: - return 0x6; - case 11: - return 0x7; - default: - return 0; - } -} - -enum cb7210_aux_cmds { -/* - * AUX_RTL2 is an undocumented aux command which causes cb7210 to assert - * (and keep asserted) local rtl message. This is used in conjunction - * with the (stupid) cb7210 implementation - * of the normal nec7210 AUX_RTL aux command, which - * causes the rtl message to toggle between on and off. - */ - AUX_RTL2 = 0xd, - AUX_LO_SPEED = 0x40, - AUX_HI_SPEED = 0x41, -}; diff --git a/drivers/staging/gpib/cec/Makefile b/drivers/staging/gpib/cec/Makefile deleted file mode 100644 index b7141e23d4e0..000000000000 --- a/drivers/staging/gpib/cec/Makefile +++ /dev/null @@ -1,3 +0,0 @@ - -obj-$(CONFIG_GPIB_CEC_PCI) += cec_gpib.o - diff --git a/drivers/staging/gpib/cec/cec.h b/drivers/staging/gpib/cec/cec.h deleted file mode 100644 index 3ce2869c7429..000000000000 --- a/drivers/staging/gpib/cec/cec.h +++ /dev/null @@ -1,20 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -#include "nec7210.h" -#include "gpibP.h" -#include "plx9050.h" - -struct cec_priv { - struct nec7210_priv nec7210_priv; - struct pci_dev *pci_device; - // base address for plx9052 pci chip - unsigned long plx_iobase; - unsigned int irq; -}; - -// offset between consecutive nec7210 registers -static const int cec_reg_offset = 1; diff --git a/drivers/staging/gpib/cec/cec_gpib.c b/drivers/staging/gpib/cec/cec_gpib.c deleted file mode 100644 index dbf9b95baabc..000000000000 --- a/drivers/staging/gpib/cec/cec_gpib.c +++ /dev/null @@ -1,393 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define DRV_NAME KBUILD_MODNAME - -#include "cec.h" -#include <linux/pci.h> -#include <linux/io.h> -#include <linux/bitops.h> -#include <asm/dma.h> -#include <linux/module.h> -#include <linux/slab.h> - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB driver for CEC PCI and PCMCIA boards"); - -/* - * GPIB interrupt service routines - */ - -static irqreturn_t cec_interrupt(int irq, void *arg) -{ - struct gpib_board *board = arg; - struct cec_priv *priv = board->private_data; - unsigned long flags; - irqreturn_t retval; - - spin_lock_irqsave(&board->spinlock, flags); - retval = nec7210_interrupt(board, &priv->nec7210_priv); - spin_unlock_irqrestore(&board->spinlock, flags); - return retval; -} - -#define CEC_VENDOR_ID 0x12fc -#define CEC_DEV_ID 0x5cec -#define CEC_SUBID 0x9050 - -static int cec_pci_attach(struct gpib_board *board, const struct gpib_board_config *config); - -static void cec_pci_detach(struct gpib_board *board); - -// wrappers for interface functions -static int cec_read(struct gpib_board *board, u8 *buffer, size_t length, int *end, - size_t *bytes_read) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); -} - -static int cec_write(struct gpib_board *board, u8 *buffer, size_t length, int send_eoi, - size_t *bytes_written) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); -} - -static int cec_command(struct gpib_board *board, u8 *buffer, - size_t length, size_t *bytes_written) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); -} - -static int cec_take_control(struct gpib_board *board, int synchronous) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_take_control(board, &priv->nec7210_priv, synchronous); -} - -static int cec_go_to_standby(struct gpib_board *board) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_go_to_standby(board, &priv->nec7210_priv); -} - -static int cec_request_system_control(struct gpib_board *board, int request_control) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_request_system_control(board, &priv->nec7210_priv, request_control); -} - -static void cec_interface_clear(struct gpib_board *board, int assert) -{ - struct cec_priv *priv = board->private_data; - - nec7210_interface_clear(board, &priv->nec7210_priv, assert); -} - -static void cec_remote_enable(struct gpib_board *board, int enable) -{ - struct cec_priv *priv = board->private_data; - - nec7210_remote_enable(board, &priv->nec7210_priv, enable); -} - -static int cec_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); -} - -static void cec_disable_eos(struct gpib_board *board) -{ - struct cec_priv *priv = board->private_data; - - nec7210_disable_eos(board, &priv->nec7210_priv); -} - -static unsigned int cec_update_status(struct gpib_board *board, unsigned int clear_mask) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); -} - -static int cec_primary_address(struct gpib_board *board, unsigned int address) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_primary_address(board, &priv->nec7210_priv, address); -} - -static int cec_secondary_address(struct gpib_board *board, unsigned int address, int enable) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); -} - -static int cec_parallel_poll(struct gpib_board *board, u8 *result) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_parallel_poll(board, &priv->nec7210_priv, result); -} - -static void cec_parallel_poll_configure(struct gpib_board *board, u8 config) -{ - struct cec_priv *priv = board->private_data; - - nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config); -} - -static void cec_parallel_poll_response(struct gpib_board *board, int ist) -{ - struct cec_priv *priv = board->private_data; - - nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); -} - -static void cec_serial_poll_response(struct gpib_board *board, u8 status) -{ - struct cec_priv *priv = board->private_data; - - nec7210_serial_poll_response(board, &priv->nec7210_priv, status); -} - -static u8 cec_serial_poll_status(struct gpib_board *board) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_serial_poll_status(board, &priv->nec7210_priv); -} - -static int cec_t1_delay(struct gpib_board *board, unsigned int nano_sec) -{ - struct cec_priv *priv = board->private_data; - - return nec7210_t1_delay(board, &priv->nec7210_priv, nano_sec); -} - -static void cec_return_to_local(struct gpib_board *board) -{ - struct cec_priv *priv = board->private_data; - - nec7210_return_to_local(board, &priv->nec7210_priv); -} - -static struct gpib_interface cec_pci_interface = { - .name = "cec_pci", - .attach = cec_pci_attach, - .detach = cec_pci_detach, - .read = cec_read, - .write = cec_write, - .command = cec_command, - .take_control = cec_take_control, - .go_to_standby = cec_go_to_standby, - .request_system_control = cec_request_system_control, - .interface_clear = cec_interface_clear, - .remote_enable = cec_remote_enable, - .enable_eos = cec_enable_eos, - .disable_eos = cec_disable_eos, - .parallel_poll = cec_parallel_poll, - .parallel_poll_configure = cec_parallel_poll_configure, - .parallel_poll_response = cec_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = NULL, // XXX - .update_status = cec_update_status, - .primary_address = cec_primary_address, - .secondary_address = cec_secondary_address, - .serial_poll_response = cec_serial_poll_response, - .serial_poll_status = cec_serial_poll_status, - .t1_delay = cec_t1_delay, - .return_to_local = cec_return_to_local, -}; - -static int cec_allocate_private(struct gpib_board *board) -{ - struct cec_priv *priv; - - board->private_data = kmalloc(sizeof(struct cec_priv), GFP_KERNEL); - if (!board->private_data) - return -1; - priv = board->private_data; - memset(priv, 0, sizeof(struct cec_priv)); - init_nec7210_private(&priv->nec7210_priv); - return 0; -} - -static void cec_free_private(struct gpib_board *board) -{ - kfree(board->private_data); - board->private_data = NULL; -} - -static int cec_generic_attach(struct gpib_board *board) -{ - struct cec_priv *cec_priv; - struct nec7210_priv *nec_priv; - - board->status = 0; - - if (cec_allocate_private(board)) - return -ENOMEM; - cec_priv = board->private_data; - nec_priv = &cec_priv->nec7210_priv; - nec_priv->read_byte = nec7210_ioport_read_byte; - nec_priv->write_byte = nec7210_ioport_write_byte; - nec_priv->offset = cec_reg_offset; - nec_priv->type = NEC7210; // guess - return 0; -} - -static void cec_init(struct cec_priv *cec_priv, const struct gpib_board *board) -{ - struct nec7210_priv *nec_priv = &cec_priv->nec7210_priv; - - nec7210_board_reset(nec_priv, board); - - /* set internal counter register for 8 MHz input clock */ - write_byte(nec_priv, ICR | 8, AUXMR); - - nec7210_board_online(nec_priv, board); -} - -static int cec_pci_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct cec_priv *cec_priv; - struct nec7210_priv *nec_priv; - int isr_flags = 0; - int retval; - - retval = cec_generic_attach(board); - if (retval) - return retval; - - cec_priv = board->private_data; - nec_priv = &cec_priv->nec7210_priv; - - // find board - cec_priv->pci_device = NULL; - while ((cec_priv->pci_device = - gpib_pci_get_device(config, CEC_VENDOR_ID, - CEC_DEV_ID, cec_priv->pci_device))) { - // check for board with plx9050 controller - if (cec_priv->pci_device->subsystem_device == CEC_SUBID) - break; - } - if (!cec_priv->pci_device) { - dev_err(board->gpib_dev, "no cec PCI board found\n"); - return -ENODEV; - } - - if (pci_enable_device(cec_priv->pci_device)) { - dev_err(board->gpib_dev, "error enabling pci device\n"); - return -EIO; - } - - if (pci_request_regions(cec_priv->pci_device, "cec-gpib")) - return -EBUSY; - - cec_priv->plx_iobase = pci_resource_start(cec_priv->pci_device, 1); - nec_priv->iobase = pci_resource_start(cec_priv->pci_device, 3); - - isr_flags |= IRQF_SHARED; - if (request_irq(cec_priv->pci_device->irq, cec_interrupt, isr_flags, DRV_NAME, board)) { - dev_err(board->gpib_dev, "failed to obtain IRQ %d\n", cec_priv->pci_device->irq); - return -EBUSY; - } - cec_priv->irq = cec_priv->pci_device->irq; - if (gpib_request_pseudo_irq(board, cec_interrupt)) { - dev_err(board->gpib_dev, "failed to allocate pseudo irq\n"); - return -1; - } - cec_init(cec_priv, board); - - // enable interrupts on plx chip - outl(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR1_POLARITY_BIT | PLX9050_PCI_INTR_EN_BIT, - cec_priv->plx_iobase + PLX9050_INTCSR_REG); - - return 0; -} - -static void cec_pci_detach(struct gpib_board *board) -{ - struct cec_priv *cec_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (cec_priv) { - nec_priv = &cec_priv->nec7210_priv; - gpib_free_pseudo_irq(board); - if (cec_priv->irq) { - // disable plx9050 interrupts - outl(0, cec_priv->plx_iobase + PLX9050_INTCSR_REG); - free_irq(cec_priv->irq, board); - } - if (nec_priv->iobase) { - nec7210_board_reset(nec_priv, board); - pci_release_regions(cec_priv->pci_device); - } - if (cec_priv->pci_device) - pci_dev_put(cec_priv->pci_device); - } - cec_free_private(board); -} - -static int cec_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - return 0; -} - -static const struct pci_device_id cec_pci_table[] = { - {CEC_VENDOR_ID, CEC_DEV_ID, PCI_ANY_ID, CEC_SUBID, 0, 0, 0 }, - {0} -}; -MODULE_DEVICE_TABLE(pci, cec_pci_table); - -static struct pci_driver cec_pci_driver = { - .name = DRV_NAME, - .id_table = cec_pci_table, - .probe = &cec_pci_probe -}; - -static int __init cec_init_module(void) -{ - int result; - - result = pci_register_driver(&cec_pci_driver); - if (result) { - pr_err("pci_register_driver failed: error = %d\n", result); - return result; - } - - result = gpib_register_driver(&cec_pci_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - return result; - } - - return 0; -} - -static void cec_exit_module(void) -{ - gpib_unregister_driver(&cec_pci_interface); - - pci_unregister_driver(&cec_pci_driver); -} - -module_init(cec_init_module); -module_exit(cec_exit_module); diff --git a/drivers/staging/gpib/common/Makefile b/drivers/staging/gpib/common/Makefile deleted file mode 100644 index 460586edb574..000000000000 --- a/drivers/staging/gpib/common/Makefile +++ /dev/null @@ -1,6 +0,0 @@ - -obj-$(CONFIG_GPIB_COMMON) += gpib_common.o - -gpib_common-objs := gpib_os.o iblib.o - - diff --git a/drivers/staging/gpib/common/gpib_os.c b/drivers/staging/gpib/common/gpib_os.c deleted file mode 100644 index 9dbbac8b8436..000000000000 --- a/drivers/staging/gpib/common/gpib_os.c +++ /dev/null @@ -1,2271 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * copyright : (C) 2001, 2004 by Frank Mori Hess - *************************************************************************** - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt - -#include "ibsys.h" -#include <linux/module.h> -#include <linux/wait.h> -#include <linux/list.h> -#include <linux/fs.h> -#include <linux/pci.h> -#include <linux/device.h> -#include <linux/init.h> -#include <linux/string.h> -#include <linux/vmalloc.h> -#include <linux/fcntl.h> -#include <linux/kmod.h> -#include <linux/uaccess.h> - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB base support"); -MODULE_ALIAS_CHARDEV_MAJOR(GPIB_CODE); - -static int board_type_ioctl(struct gpib_file_private *file_priv, - struct gpib_board *board, unsigned long arg); -static int read_ioctl(struct gpib_file_private *file_priv, struct gpib_board *board, - unsigned long arg); -static int write_ioctl(struct gpib_file_private *file_priv, struct gpib_board *board, - unsigned long arg); -static int command_ioctl(struct gpib_file_private *file_priv, struct gpib_board *board, - unsigned long arg); -static int open_dev_ioctl(struct file *filep, struct gpib_board *board, unsigned long arg); -static int close_dev_ioctl(struct file *filep, struct gpib_board *board, unsigned long arg); -static int serial_poll_ioctl(struct gpib_board *board, unsigned long arg); -static int wait_ioctl(struct gpib_file_private *file_priv, - struct gpib_board *board, unsigned long arg); -static int parallel_poll_ioctl(struct gpib_board *board, unsigned long arg); -static int online_ioctl(struct gpib_board *board, unsigned long arg); -static int remote_enable_ioctl(struct gpib_board *board, unsigned long arg); -static int take_control_ioctl(struct gpib_board *board, unsigned long arg); -static int line_status_ioctl(struct gpib_board *board, unsigned long arg); -static int pad_ioctl(struct gpib_board *board, struct gpib_file_private *file_priv, - unsigned long arg); -static int sad_ioctl(struct gpib_board *board, struct gpib_file_private *file_priv, - unsigned long arg); -static int eos_ioctl(struct gpib_board *board, unsigned long arg); -static int request_service_ioctl(struct gpib_board *board, unsigned long arg); -static int request_service2_ioctl(struct gpib_board *board, unsigned long arg); -static int iobase_ioctl(struct gpib_board_config *config, unsigned long arg); -static int irq_ioctl(struct gpib_board_config *config, unsigned long arg); -static int dma_ioctl(struct gpib_board_config *config, unsigned long arg); -static int autospoll_ioctl(struct gpib_board *board, struct gpib_file_private *file_priv, - unsigned long arg); -static int mutex_ioctl(struct gpib_board *board, struct gpib_file_private *file_priv, - unsigned long arg); -static int timeout_ioctl(struct gpib_board *board, unsigned long arg); -static int status_bytes_ioctl(struct gpib_board *board, unsigned long arg); -static int board_info_ioctl(const struct gpib_board *board, unsigned long arg); -static int ppc_ioctl(struct gpib_board *board, unsigned long arg); -static int set_local_ppoll_mode_ioctl(struct gpib_board *board, unsigned long arg); -static int get_local_ppoll_mode_ioctl(struct gpib_board *board, unsigned long arg); -static int query_board_rsv_ioctl(struct gpib_board *board, unsigned long arg); -static int interface_clear_ioctl(struct gpib_board *board, unsigned long arg); -static int select_pci_ioctl(struct gpib_board_config *config, unsigned long arg); -static int select_device_path_ioctl(struct gpib_board_config *config, unsigned long arg); -static int event_ioctl(struct gpib_board *board, unsigned long arg); -static int request_system_control_ioctl(struct gpib_board *board, unsigned long arg); -static int t1_delay_ioctl(struct gpib_board *board, unsigned long arg); - -static int cleanup_open_devices(struct gpib_file_private *file_priv, struct gpib_board *board); - -static int pop_gpib_event_nolock(struct gpib_board *board, - struct gpib_event_queue *queue, short *event_type); - -/* - * Timer functions - */ - -/* Watchdog timeout routine */ - -static void watchdog_timeout(struct timer_list *t) -{ - struct gpib_board *board = timer_container_of(board, t, timer); - - set_bit(TIMO_NUM, &board->status); - wake_up_interruptible(&board->wait); -} - -/* install timer interrupt handler */ -void os_start_timer(struct gpib_board *board, unsigned int usec_timeout) -/* Starts the timeout task */ -{ - if (timer_pending(&board->timer)) { - dev_err(board->gpib_dev, "bug! timer already running?\n"); - return; - } - clear_bit(TIMO_NUM, &board->status); - - if (usec_timeout > 0) { - board->timer.function = watchdog_timeout; - /* set number of ticks */ - mod_timer(&board->timer, jiffies + usec_to_jiffies(usec_timeout)); - } -} - -void os_remove_timer(struct gpib_board *board) -/* Removes the timeout task */ -{ - if (timer_pending(&board->timer)) - timer_delete_sync(&board->timer); -} - -int io_timed_out(struct gpib_board *board) -{ - if (test_bit(TIMO_NUM, &board->status)) - return 1; - return 0; -} - -/* - * this is a function instead of a constant because of Suse - * defining HZ to be a function call to get_hz() - */ -static inline int pseudo_irq_period(void) -{ - return (HZ + 99) / 100; -} - -static void pseudo_irq_handler(struct timer_list *t) -{ - struct gpib_pseudo_irq *pseudo_irq = timer_container_of(pseudo_irq, t, - timer); - - if (pseudo_irq->handler) - pseudo_irq->handler(0, pseudo_irq->board); - else - pr_err("gpib: bug! pseudo_irq.handler is NULL\n"); - - if (atomic_read(&pseudo_irq->active)) - mod_timer(&pseudo_irq->timer, jiffies + pseudo_irq_period()); -} - -int gpib_request_pseudo_irq(struct gpib_board *board, irqreturn_t (*handler)(int, void *)) -{ - if (timer_pending(&board->pseudo_irq.timer) || board->pseudo_irq.handler) { - dev_err(board->gpib_dev, "only one pseudo interrupt per board allowed\n"); - return -1; - } - - board->pseudo_irq.handler = handler; - board->pseudo_irq.timer.function = pseudo_irq_handler; - board->pseudo_irq.board = board; - - atomic_set(&board->pseudo_irq.active, 1); - - mod_timer(&board->pseudo_irq.timer, jiffies + pseudo_irq_period()); - - return 0; -} -EXPORT_SYMBOL(gpib_request_pseudo_irq); - -void gpib_free_pseudo_irq(struct gpib_board *board) -{ - atomic_set(&board->pseudo_irq.active, 0); - - timer_delete_sync(&board->pseudo_irq.timer); - board->pseudo_irq.handler = NULL; -} -EXPORT_SYMBOL(gpib_free_pseudo_irq); - -static const unsigned int serial_timeout = 1000000; - -unsigned int num_status_bytes(const struct gpib_status_queue *dev) -{ - if (!dev) - return 0; - return dev->num_status_bytes; -} - -// push status byte onto back of status byte fifo -int push_status_byte(struct gpib_board *board, struct gpib_status_queue *device, u8 poll_byte) -{ - struct list_head *head = &device->status_bytes; - struct gpib_status_byte *status; - static const unsigned int max_num_status_bytes = 1024; - int retval; - - if (num_status_bytes(device) >= max_num_status_bytes) { - u8 lost_byte; - - device->dropped_byte = 1; - retval = pop_status_byte(board, device, &lost_byte); - if (retval < 0) - return retval; - } - - status = kmalloc(sizeof(*status), GFP_KERNEL); - if (!status) - return -ENOMEM; - - INIT_LIST_HEAD(&status->list); - status->poll_byte = poll_byte; - - list_add_tail(&status->list, head); - - device->num_status_bytes++; - - dev_dbg(board->gpib_dev, "pushed status byte 0x%x, %i in queue\n", - (int)poll_byte, num_status_bytes(device)); - - return 0; -} - -// pop status byte from front of status byte fifo -int pop_status_byte(struct gpib_board *board, struct gpib_status_queue *device, u8 *poll_byte) -{ - struct list_head *head = &device->status_bytes; - struct list_head *front = head->next; - struct gpib_status_byte *status; - - if (num_status_bytes(device) == 0) - return -EIO; - - if (front == head) - return -EIO; - - if (device->dropped_byte) { - device->dropped_byte = 0; - return -EPIPE; - } - - status = list_entry(front, struct gpib_status_byte, list); - *poll_byte = status->poll_byte; - - list_del(front); - kfree(status); - - device->num_status_bytes--; - - dev_dbg(board->gpib_dev, "popped status byte 0x%x, %i in queue\n", - (int)*poll_byte, num_status_bytes(device)); - - return 0; -} - -struct gpib_status_queue *get_gpib_status_queue(struct gpib_board *board, unsigned int pad, int sad) -{ - struct gpib_status_queue *device; - struct list_head *list_ptr; - const struct list_head *head = &board->device_list; - - for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) { - device = list_entry(list_ptr, struct gpib_status_queue, list); - if (gpib_address_equal(device->pad, device->sad, pad, sad)) - return device; - } - - return NULL; -} - -int get_serial_poll_byte(struct gpib_board *board, unsigned int pad, int sad, - unsigned int usec_timeout, u8 *poll_byte) -{ - struct gpib_status_queue *device; - - device = get_gpib_status_queue(board, pad, sad); - if (num_status_bytes(device)) - return pop_status_byte(board, device, poll_byte); - else - return dvrsp(board, pad, sad, usec_timeout, poll_byte); -} - -int autopoll_all_devices(struct gpib_board *board) -{ - int retval; - - if (mutex_lock_interruptible(&board->user_mutex)) - return -ERESTARTSYS; - if (mutex_lock_interruptible(&board->big_gpib_mutex)) { - mutex_unlock(&board->user_mutex); - return -ERESTARTSYS; - } - - dev_dbg(board->gpib_dev, "autopoll has board lock\n"); - - retval = serial_poll_all(board, serial_timeout); - if (retval < 0) { - mutex_unlock(&board->big_gpib_mutex); - mutex_unlock(&board->user_mutex); - return retval; - } - - dev_dbg(board->gpib_dev, "complete\n"); - /* - * need to wake wait queue in case someone is - * waiting on RQS - */ - wake_up_interruptible(&board->wait); - mutex_unlock(&board->big_gpib_mutex); - mutex_unlock(&board->user_mutex); - - return retval; -} - -static int setup_serial_poll(struct gpib_board *board, unsigned int usec_timeout) -{ - u8 cmd_string[8]; - int i; - size_t bytes_written; - int ret; - - os_start_timer(board, usec_timeout); - ret = ibcac(board, 1, 1); - if (ret < 0) { - os_remove_timer(board); - return ret; - } - - i = 0; - cmd_string[i++] = UNL; - cmd_string[i++] = MLA(board->pad); /* controller's listen address */ - if (board->sad >= 0) - cmd_string[i++] = MSA(board->sad); - cmd_string[i++] = SPE; // serial poll enable - - ret = board->interface->command(board, cmd_string, i, &bytes_written); - if (ret < 0 || bytes_written < i) { - dev_dbg(board->gpib_dev, "failed to setup serial poll\n"); - os_remove_timer(board); - return -EIO; - } - os_remove_timer(board); - - return 0; -} - -static int read_serial_poll_byte(struct gpib_board *board, unsigned int pad, - int sad, unsigned int usec_timeout, u8 *result) -{ - u8 cmd_string[8]; - int end_flag; - int ret; - int i; - size_t nbytes; - - dev_dbg(board->gpib_dev, "entering pad=%i sad=%i\n", pad, sad); - - os_start_timer(board, usec_timeout); - ret = ibcac(board, 1, 1); - if (ret < 0) { - os_remove_timer(board); - return ret; - } - - i = 0; - // send talk address - cmd_string[i++] = MTA(pad); - if (sad >= 0) - cmd_string[i++] = MSA(sad); - - ret = board->interface->command(board, cmd_string, i, &nbytes); - if (ret < 0 || nbytes < i) { - dev_err(board->gpib_dev, "failed to setup serial poll\n"); - os_remove_timer(board); - return -EIO; - } - - ibgts(board); - - // read poll result - ret = board->interface->read(board, result, 1, &end_flag, &nbytes); - if (ret < 0 || nbytes < 1) { - dev_err(board->gpib_dev, "serial poll failed\n"); - os_remove_timer(board); - return -EIO; - } - os_remove_timer(board); - - return 0; -} - -static int cleanup_serial_poll(struct gpib_board *board, unsigned int usec_timeout) -{ - u8 cmd_string[8]; - int ret; - size_t bytes_written; - - os_start_timer(board, usec_timeout); - ret = ibcac(board, 1, 1); - if (ret < 0) { - os_remove_timer(board); - return ret; - } - - cmd_string[0] = SPD; /* disable serial poll bytes */ - cmd_string[1] = UNT; - ret = board->interface->command(board, cmd_string, 2, &bytes_written); - if (ret < 0 || bytes_written < 2) { - dev_err(board->gpib_dev, "failed to disable serial poll\n"); - os_remove_timer(board); - return -EIO; - } - os_remove_timer(board); - - return 0; -} - -static int serial_poll_single(struct gpib_board *board, unsigned int pad, int sad, - unsigned int usec_timeout, u8 *result) -{ - int retval, cleanup_retval; - - retval = setup_serial_poll(board, usec_timeout); - if (retval < 0) - return retval; - retval = read_serial_poll_byte(board, pad, sad, usec_timeout, result); - cleanup_retval = cleanup_serial_poll(board, usec_timeout); - if (retval < 0) - return retval; - if (cleanup_retval < 0) - return retval; - - return 0; -} - -int serial_poll_all(struct gpib_board *board, unsigned int usec_timeout) -{ - int retval = 0; - struct list_head *cur; - const struct list_head *head = NULL; - struct gpib_status_queue *device; - u8 result; - unsigned int num_bytes = 0; - - head = &board->device_list; - if (head->next == head) - return 0; - - retval = setup_serial_poll(board, usec_timeout); - if (retval < 0) - return retval; - - for (cur = head->next; cur != head; cur = cur->next) { - device = list_entry(cur, struct gpib_status_queue, list); - retval = read_serial_poll_byte(board, - device->pad, device->sad, usec_timeout, &result); - if (retval < 0) - continue; - if (result & request_service_bit) { - retval = push_status_byte(board, device, result); - if (retval < 0) - continue; - num_bytes++; - } - } - - retval = cleanup_serial_poll(board, usec_timeout); - if (retval < 0) - return retval; - - return num_bytes; -} - -/* - * DVRSP - * This function performs a serial poll of the device with primary - * address pad and secondary address sad. If the device has no - * secondary address, pass a negative number in for this argument. At the - * end of a successful serial poll the response is returned in result. - * SPD and UNT are sent at the completion of the poll. - */ - -int dvrsp(struct gpib_board *board, unsigned int pad, int sad, - unsigned int usec_timeout, u8 *result) -{ - int status = ibstatus(board); - int retval; - - if ((status & CIC) == 0) { - dev_err(board->gpib_dev, "not CIC during serial poll\n"); - return -1; - } - - if (pad > MAX_GPIB_PRIMARY_ADDRESS || sad > MAX_GPIB_SECONDARY_ADDRESS || sad < -1) { - dev_err(board->gpib_dev, "bad address for serial poll"); - return -1; - } - - retval = serial_poll_single(board, pad, sad, usec_timeout, result); - if (io_timed_out(board)) - retval = -ETIMEDOUT; - - return retval; -} - -static struct gpib_descriptor *handle_to_descriptor(const struct gpib_file_private *file_priv, - int handle) -{ - if (handle < 0 || handle >= GPIB_MAX_NUM_DESCRIPTORS) { - pr_err("gpib: invalid handle %i\n", handle); - return NULL; - } - - return file_priv->descriptors[handle]; -} - -static int init_gpib_file_private(struct gpib_file_private *priv) -{ - memset(priv, 0, sizeof(*priv)); - atomic_set(&priv->holding_mutex, 0); - priv->descriptors[0] = kmalloc(sizeof(struct gpib_descriptor), GFP_KERNEL); - if (!priv->descriptors[0]) { - pr_err("gpib: failed to allocate default board descriptor\n"); - return -ENOMEM; - } - init_gpib_descriptor(priv->descriptors[0]); - priv->descriptors[0]->is_board = 1; - mutex_init(&priv->descriptors_mutex); - return 0; -} - -int ibopen(struct inode *inode, struct file *filep) -{ - unsigned int minor = iminor(inode); - struct gpib_board *board; - struct gpib_file_private *priv; - - if (minor >= GPIB_MAX_NUM_BOARDS) { - pr_err("gpib: invalid minor number of device file\n"); - return -ENXIO; - } - - board = &board_array[minor]; - - filep->private_data = kmalloc(sizeof(struct gpib_file_private), GFP_KERNEL); - if (!filep->private_data) - return -ENOMEM; - - priv = filep->private_data; - init_gpib_file_private((struct gpib_file_private *)filep->private_data); - - if (board->use_count == 0) { - int retval; - - retval = request_module("gpib%i", minor); - if (retval) - dev_dbg(board->gpib_dev, "request module returned %i\n", retval); - } - if (board->interface) { - if (!try_module_get(board->provider_module)) { - dev_err(board->gpib_dev, "try_module_get() failed\n"); - return -EIO; - } - board->use_count++; - priv->got_module = 1; - } - return 0; -} - -int ibclose(struct inode *inode, struct file *filep) -{ - unsigned int minor = iminor(inode); - struct gpib_board *board; - struct gpib_file_private *priv = filep->private_data; - struct gpib_descriptor *desc; - - if (minor >= GPIB_MAX_NUM_BOARDS) { - pr_err("gpib: invalid minor number of device file\n"); - return -ENODEV; - } - - board = &board_array[minor]; - - if (priv) { - desc = handle_to_descriptor(priv, 0); - if (desc) { - if (desc->autopoll_enabled) { - dev_dbg(board->gpib_dev, "decrementing autospollers\n"); - if (board->autospollers > 0) - board->autospollers--; - else - dev_err(board->gpib_dev, - "Attempt to decrement zero autospollers\n"); - } - } else { - dev_err(board->gpib_dev, "Unexpected null gpib_descriptor\n"); - } - - cleanup_open_devices(priv, board); - - if (atomic_read(&priv->holding_mutex)) - mutex_unlock(&board->user_mutex); - - if (priv->got_module && board->use_count) { - module_put(board->provider_module); - --board->use_count; - } - - kfree(filep->private_data); - filep->private_data = NULL; - } - - return 0; -} - -long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg) -{ - unsigned int minor = iminor(file_inode(filep)); - struct gpib_board *board; - struct gpib_file_private *file_priv = filep->private_data; - long retval = -ENOTTY; - - if (minor >= GPIB_MAX_NUM_BOARDS) { - pr_err("gpib: invalid minor number of device file\n"); - return -ENODEV; - } - board = &board_array[minor]; - - if (mutex_lock_interruptible(&board->big_gpib_mutex)) - return -ERESTARTSYS; - - dev_dbg(board->gpib_dev, "ioctl %d, interface=%s, use=%d, onl=%d\n", - cmd & 0xff, - board->interface ? board->interface->name : "", - board->use_count, - board->online); - - switch (cmd) { - case CFCBOARDTYPE: - retval = board_type_ioctl(file_priv, board, arg); - goto done; - case IBONL: - retval = online_ioctl(board, arg); - goto done; - default: - break; - } - if (!board->interface) { - dev_err(board->gpib_dev, "no gpib board configured\n"); - retval = -ENODEV; - goto done; - } - if (file_priv->got_module == 0) { - if (!try_module_get(board->provider_module)) { - dev_err(board->gpib_dev, "try_module_get() failed\n"); - retval = -EIO; - goto done; - } - file_priv->got_module = 1; - board->use_count++; - } - switch (cmd) { - case CFCBASE: - retval = iobase_ioctl(&board->config, arg); - goto done; - case CFCIRQ: - retval = irq_ioctl(&board->config, arg); - goto done; - case CFCDMA: - retval = dma_ioctl(&board->config, arg); - goto done; - case IBAUTOSPOLL: - retval = autospoll_ioctl(board, file_priv, arg); - goto done; - case IBBOARD_INFO: - retval = board_info_ioctl(board, arg); - goto done; - case IBMUTEX: - /* - * Need to unlock board->big_gpib_mutex before potentially locking board->user_mutex - * to maintain consistent locking order - */ - mutex_unlock(&board->big_gpib_mutex); - return mutex_ioctl(board, file_priv, arg); - case IBPAD: - retval = pad_ioctl(board, file_priv, arg); - goto done; - case IBSAD: - retval = sad_ioctl(board, file_priv, arg); - goto done; - case IBSELECT_PCI: - retval = select_pci_ioctl(&board->config, arg); - goto done; - case IBSELECT_DEVICE_PATH: - retval = select_device_path_ioctl(&board->config, arg); - goto done; - default: - break; - } - - if (!board->online) { - retval = -EINVAL; - goto done; - } - - switch (cmd) { - case IBEVENT: - retval = event_ioctl(board, arg); - goto done; - case IBCLOSEDEV: - retval = close_dev_ioctl(filep, board, arg); - goto done; - case IBOPENDEV: - retval = open_dev_ioctl(filep, board, arg); - goto done; - case IBSPOLL_BYTES: - retval = status_bytes_ioctl(board, arg); - goto done; - case IBWAIT: - retval = wait_ioctl(file_priv, board, arg); - if (retval == -ERESTARTSYS) - return retval; - goto done; - case IBLINES: - retval = line_status_ioctl(board, arg); - goto done; - case IBLOC: - board->interface->return_to_local(board); - retval = 0; - goto done; - default: - break; - } - - spin_lock(&board->locking_pid_spinlock); - if (current->pid != board->locking_pid) { - spin_unlock(&board->locking_pid_spinlock); - retval = -EPERM; - goto done; - } - spin_unlock(&board->locking_pid_spinlock); - - switch (cmd) { - case IB_T1_DELAY: - retval = t1_delay_ioctl(board, arg); - goto done; - case IBCAC: - retval = take_control_ioctl(board, arg); - goto done; - case IBCMD: - /* - * IO ioctls can take a long time, we need to unlock board->big_gpib_mutex - * before we call them. - */ - mutex_unlock(&board->big_gpib_mutex); - return command_ioctl(file_priv, board, arg); - case IBEOS: - retval = eos_ioctl(board, arg); - goto done; - case IBGTS: - retval = ibgts(board); - goto done; - case IBPPC: - retval = ppc_ioctl(board, arg); - goto done; - case IBPP2_SET: - retval = set_local_ppoll_mode_ioctl(board, arg); - goto done; - case IBPP2_GET: - retval = get_local_ppoll_mode_ioctl(board, arg); - goto done; - case IBQUERY_BOARD_RSV: - retval = query_board_rsv_ioctl(board, arg); - goto done; - case IBRD: - /* - * IO ioctls can take a long time, we need to unlock board->big_gpib_mutex - * before we call them. - */ - mutex_unlock(&board->big_gpib_mutex); - return read_ioctl(file_priv, board, arg); - case IBRPP: - retval = parallel_poll_ioctl(board, arg); - goto done; - case IBRSC: - retval = request_system_control_ioctl(board, arg); - goto done; - case IBRSP: - retval = serial_poll_ioctl(board, arg); - goto done; - case IBRSV: - retval = request_service_ioctl(board, arg); - goto done; - case IBRSV2: - retval = request_service2_ioctl(board, arg); - goto done; - case IBSIC: - retval = interface_clear_ioctl(board, arg); - goto done; - case IBSRE: - retval = remote_enable_ioctl(board, arg); - goto done; - case IBTMO: - retval = timeout_ioctl(board, arg); - goto done; - case IBWRT: - /* - * IO ioctls can take a long time, we need to unlock board->big_gpib_mutex - * before we call them. - */ - mutex_unlock(&board->big_gpib_mutex); - return write_ioctl(file_priv, board, arg); - default: - retval = -ENOTTY; - goto done; - } - -done: - mutex_unlock(&board->big_gpib_mutex); - dev_dbg(board->gpib_dev, "ioctl done status = 0x%lx\n", board->status); - return retval; -} - -static int board_type_ioctl(struct gpib_file_private *file_priv, - struct gpib_board *board, unsigned long arg) -{ - struct list_head *list_ptr; - struct gpib_board_type_ioctl cmd; - int retval; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (board->online) - return -EBUSY; - - retval = copy_from_user(&cmd, (void __user *)arg, - sizeof(struct gpib_board_type_ioctl)); - if (retval) - return -EFAULT; - - for (list_ptr = registered_drivers.next; list_ptr != ®istered_drivers; - list_ptr = list_ptr->next) { - struct gpib_interface_list *entry; - - entry = list_entry(list_ptr, struct gpib_interface_list, list); - if (strcmp(entry->interface->name, cmd.name) == 0) { - int i; - int had_module = file_priv->got_module; - - if (board->use_count) { - for (i = 0; i < board->use_count; ++i) - module_put(board->provider_module); - board->interface = NULL; - file_priv->got_module = 0; - } - board->interface = entry->interface; - board->provider_module = entry->module; - for (i = 0; i < board->use_count; ++i) { - if (!try_module_get(entry->module)) { - board->use_count = i; - return -EIO; - } - } - if (had_module == 0) { - if (!try_module_get(entry->module)) - return -EIO; - ++board->use_count; - } - file_priv->got_module = 1; - return 0; - } - } - - return -EINVAL; -} - -static int read_ioctl(struct gpib_file_private *file_priv, struct gpib_board *board, - unsigned long arg) -{ - struct gpib_read_write_ioctl read_cmd; - u8 __user *userbuf; - unsigned long remain; - int end_flag = 0; - int retval; - ssize_t read_ret = 0; - struct gpib_descriptor *desc; - size_t nbytes; - - retval = copy_from_user(&read_cmd, (void __user *)arg, sizeof(read_cmd)); - if (retval) - return -EFAULT; - - if (read_cmd.completed_transfer_count > read_cmd.requested_transfer_count) - return -EINVAL; - - desc = handle_to_descriptor(file_priv, read_cmd.handle); - if (!desc) - return -EINVAL; - - if (WARN_ON_ONCE(sizeof(userbuf) > sizeof(read_cmd.buffer_ptr))) - return -EFAULT; - - userbuf = (u8 __user *)(unsigned long)read_cmd.buffer_ptr; - userbuf += read_cmd.completed_transfer_count; - - remain = read_cmd.requested_transfer_count - read_cmd.completed_transfer_count; - - /* Check write access to buffer */ - if (!access_ok(userbuf, remain)) - return -EFAULT; - - atomic_set(&desc->io_in_progress, 1); - - /* Read buffer loads till we fill the user supplied buffer */ - while (remain > 0 && end_flag == 0) { - nbytes = 0; - read_ret = ibrd(board, board->buffer, (board->buffer_length < remain) ? - board->buffer_length : remain, &end_flag, &nbytes); - if (nbytes == 0) - break; - retval = copy_to_user(userbuf, board->buffer, nbytes); - if (retval) { - retval = -EFAULT; - break; - } - remain -= nbytes; - userbuf += nbytes; - if (read_ret < 0) - break; - } - read_cmd.completed_transfer_count = read_cmd.requested_transfer_count - remain; - read_cmd.end = end_flag; - /* - * suppress errors (for example due to timeout or interruption by device clear) - * if all bytes got sent. This prevents races that can occur in the various drivers - * if a device receives a device clear immediately after a transfer completes and - * the driver code wasn't careful enough to handle that case. - */ - if (remain == 0 || end_flag) - read_ret = 0; - if (retval == 0) - retval = copy_to_user((void __user *)arg, &read_cmd, sizeof(read_cmd)); - - atomic_set(&desc->io_in_progress, 0); - - wake_up_interruptible(&board->wait); - if (retval) - return -EFAULT; - - return read_ret; -} - -static int command_ioctl(struct gpib_file_private *file_priv, - struct gpib_board *board, unsigned long arg) -{ - struct gpib_read_write_ioctl cmd; - u8 __user *userbuf; - unsigned long remain; - int retval; - int fault = 0; - struct gpib_descriptor *desc; - size_t bytes_written; - int no_clear_io_in_prog; - - retval = copy_from_user(&cmd, (void __user *)arg, sizeof(cmd)); - if (retval) - return -EFAULT; - - if (cmd.completed_transfer_count > cmd.requested_transfer_count) - return -EINVAL; - - desc = handle_to_descriptor(file_priv, cmd.handle); - if (!desc) - return -EINVAL; - - userbuf = (u8 __user *)(unsigned long)cmd.buffer_ptr; - userbuf += cmd.completed_transfer_count; - - no_clear_io_in_prog = cmd.end; - cmd.end = 0; - - remain = cmd.requested_transfer_count - cmd.completed_transfer_count; - - /* Check read access to buffer */ - if (!access_ok(userbuf, remain)) - return -EFAULT; - - /* - * Write buffer loads till we empty the user supplied buffer. - * Call drivers at least once, even if remain is zero, in - * order to allow them to insure previous commands were - * completely finished, in the case of a restarted ioctl. - */ - - atomic_set(&desc->io_in_progress, 1); - - do { - fault = copy_from_user(board->buffer, userbuf, (board->buffer_length < remain) ? - board->buffer_length : remain); - if (fault) { - retval = -EFAULT; - bytes_written = 0; - } else { - retval = ibcmd(board, board->buffer, (board->buffer_length < remain) ? - board->buffer_length : remain, &bytes_written); - } - remain -= bytes_written; - userbuf += bytes_written; - if (retval < 0) { - atomic_set(&desc->io_in_progress, 0); - - wake_up_interruptible(&board->wait); - break; - } - } while (remain > 0); - - cmd.completed_transfer_count = cmd.requested_transfer_count - remain; - - if (fault == 0) - fault = copy_to_user((void __user *)arg, &cmd, sizeof(cmd)); - - /* - * no_clear_io_in_prog (cmd.end) is true when io_in_progress should - * not be set to zero because the cmd in progress is the address setup - * operation for an async read or write. This causes CMPL not to be set - * in general_ibstatus until the async read or write completes. - */ - if (!no_clear_io_in_prog || fault) - atomic_set(&desc->io_in_progress, 0); - - wake_up_interruptible(&board->wait); - if (fault) - return -EFAULT; - - return retval; -} - -static int write_ioctl(struct gpib_file_private *file_priv, struct gpib_board *board, - unsigned long arg) -{ - struct gpib_read_write_ioctl write_cmd; - u8 __user *userbuf; - unsigned long remain; - int retval = 0; - int fault; - struct gpib_descriptor *desc; - - fault = copy_from_user(&write_cmd, (void __user *)arg, sizeof(write_cmd)); - if (fault) - return -EFAULT; - - if (write_cmd.completed_transfer_count > write_cmd.requested_transfer_count) - return -EINVAL; - - desc = handle_to_descriptor(file_priv, write_cmd.handle); - if (!desc) - return -EINVAL; - - userbuf = (u8 __user *)(unsigned long)write_cmd.buffer_ptr; - userbuf += write_cmd.completed_transfer_count; - - remain = write_cmd.requested_transfer_count - write_cmd.completed_transfer_count; - - /* Check read access to buffer */ - if (!access_ok(userbuf, remain)) - return -EFAULT; - - atomic_set(&desc->io_in_progress, 1); - - /* Write buffer loads till we empty the user supplied buffer */ - while (remain > 0) { - int send_eoi; - size_t bytes_written = 0; - - send_eoi = remain <= board->buffer_length && write_cmd.end; - fault = copy_from_user(board->buffer, userbuf, (board->buffer_length < remain) ? - board->buffer_length : remain); - if (fault) { - retval = -EFAULT; - break; - } - retval = ibwrt(board, board->buffer, (board->buffer_length < remain) ? - board->buffer_length : remain, send_eoi, &bytes_written); - remain -= bytes_written; - userbuf += bytes_written; - if (retval < 0) - break; - } - write_cmd.completed_transfer_count = write_cmd.requested_transfer_count - remain; - /* - * suppress errors (for example due to timeout or interruption by device clear) - * if all bytes got sent. This prevents races that can occur in the various drivers - * if a device receives a device clear immediately after a transfer completes and - * the driver code wasn't careful enough to handle that case. - */ - if (remain == 0) - retval = 0; - if (fault == 0) - fault = copy_to_user((void __user *)arg, &write_cmd, sizeof(write_cmd)); - - atomic_set(&desc->io_in_progress, 0); - - wake_up_interruptible(&board->wait); - if (fault) - return -EFAULT; - - return retval; -} - -static int status_bytes_ioctl(struct gpib_board *board, unsigned long arg) -{ - struct gpib_status_queue *device; - struct gpib_spoll_bytes_ioctl cmd; - int retval; - - retval = copy_from_user(&cmd, (void __user *)arg, sizeof(cmd)); - if (retval) - return -EFAULT; - - device = get_gpib_status_queue(board, cmd.pad, cmd.sad); - if (!device) - cmd.num_bytes = 0; - else - cmd.num_bytes = num_status_bytes(device); - - retval = copy_to_user((void __user *)arg, &cmd, sizeof(cmd)); - if (retval) - return -EFAULT; - - return 0; -} - -static int increment_open_device_count(struct gpib_board *board, struct list_head *head, - unsigned int pad, int sad) -{ - struct list_head *list_ptr; - struct gpib_status_queue *device; - - /* - * first see if address has already been opened, then increment - * open count - */ - for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) { - device = list_entry(list_ptr, struct gpib_status_queue, list); - if (gpib_address_equal(device->pad, device->sad, pad, sad)) { - dev_dbg(board->gpib_dev, "incrementing open count for pad %i, sad %i\n", - device->pad, device->sad); - device->reference_count++; - return 0; - } - } - - /* otherwise we need to allocate a new struct gpib_status_queue */ - device = kmalloc(sizeof(struct gpib_status_queue), GFP_ATOMIC); - if (!device) - return -ENOMEM; - init_gpib_status_queue(device); - device->pad = pad; - device->sad = sad; - device->reference_count = 1; - - list_add(&device->list, head); - - dev_dbg(board->gpib_dev, "opened pad %i, sad %i\n", device->pad, device->sad); - - return 0; -} - -static int subtract_open_device_count(struct gpib_board *board, struct list_head *head, - unsigned int pad, int sad, unsigned int count) -{ - struct gpib_status_queue *device; - struct list_head *list_ptr; - - for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) { - device = list_entry(list_ptr, struct gpib_status_queue, list); - if (gpib_address_equal(device->pad, device->sad, pad, sad)) { - dev_dbg(board->gpib_dev, "decrementing open count for pad %i, sad %i\n", - device->pad, device->sad); - if (count > device->reference_count) { - dev_err(board->gpib_dev, "bug! in %s()\n", __func__); - return -EINVAL; - } - device->reference_count -= count; - if (device->reference_count == 0) { - dev_dbg(board->gpib_dev, "closing pad %i, sad %i\n", - device->pad, device->sad); - list_del(list_ptr); - kfree(device); - } - return 0; - } - } - dev_err(board->gpib_dev, "bug! tried to close address that was never opened!\n"); - return -EINVAL; -} - -static inline int decrement_open_device_count(struct gpib_board *board, struct list_head *head, - unsigned int pad, int sad) -{ - return subtract_open_device_count(board, head, pad, sad, 1); -} - -static int cleanup_open_devices(struct gpib_file_private *file_priv, struct gpib_board *board) -{ - int retval = 0; - int i; - - for (i = 0; i < GPIB_MAX_NUM_DESCRIPTORS; i++) { - struct gpib_descriptor *desc; - - desc = file_priv->descriptors[i]; - if (!desc) - continue; - - if (desc->is_board == 0) { - retval = decrement_open_device_count(board, &board->device_list, desc->pad, - desc->sad); - if (retval < 0) - return retval; - } - kfree(desc); - file_priv->descriptors[i] = NULL; - } - - return 0; -} - -static int open_dev_ioctl(struct file *filep, struct gpib_board *board, unsigned long arg) -{ - struct gpib_open_dev_ioctl open_dev_cmd; - int retval; - struct gpib_file_private *file_priv = filep->private_data; - int i; - - retval = copy_from_user(&open_dev_cmd, (void __user *)arg, sizeof(open_dev_cmd)); - if (retval) - return -EFAULT; - - if (mutex_lock_interruptible(&file_priv->descriptors_mutex)) - return -ERESTARTSYS; - for (i = 0; i < GPIB_MAX_NUM_DESCRIPTORS; i++) - if (!file_priv->descriptors[i]) - break; - if (i == GPIB_MAX_NUM_DESCRIPTORS) { - mutex_unlock(&file_priv->descriptors_mutex); - return -ERANGE; - } - file_priv->descriptors[i] = kmalloc(sizeof(struct gpib_descriptor), GFP_KERNEL); - if (!file_priv->descriptors[i]) { - mutex_unlock(&file_priv->descriptors_mutex); - return -ENOMEM; - } - init_gpib_descriptor(file_priv->descriptors[i]); - - file_priv->descriptors[i]->pad = open_dev_cmd.pad; - file_priv->descriptors[i]->sad = open_dev_cmd.sad; - file_priv->descriptors[i]->is_board = open_dev_cmd.is_board; - mutex_unlock(&file_priv->descriptors_mutex); - - retval = increment_open_device_count(board, &board->device_list, open_dev_cmd.pad, - open_dev_cmd.sad); - if (retval < 0) - return retval; - - /* - * clear stuck srq state, since we may be able to find service request on - * the new device - */ - atomic_set(&board->stuck_srq, 0); - - open_dev_cmd.handle = i; - retval = copy_to_user((void __user *)arg, &open_dev_cmd, sizeof(open_dev_cmd)); - if (retval) - return -EFAULT; - - return 0; -} - -static int close_dev_ioctl(struct file *filep, struct gpib_board *board, unsigned long arg) -{ - struct gpib_close_dev_ioctl cmd; - struct gpib_file_private *file_priv = filep->private_data; - int retval; - - retval = copy_from_user(&cmd, (void __user *)arg, sizeof(cmd)); - if (retval) - return -EFAULT; - - if (cmd.handle >= GPIB_MAX_NUM_DESCRIPTORS) - return -EINVAL; - if (!file_priv->descriptors[cmd.handle]) - return -EINVAL; - - retval = decrement_open_device_count(board, &board->device_list, - file_priv->descriptors[cmd.handle]->pad, - file_priv->descriptors[cmd.handle]->sad); - if (retval < 0) - return retval; - - kfree(file_priv->descriptors[cmd.handle]); - file_priv->descriptors[cmd.handle] = NULL; - - return 0; -} - -static int serial_poll_ioctl(struct gpib_board *board, unsigned long arg) -{ - struct gpib_serial_poll_ioctl serial_cmd; - int retval; - - retval = copy_from_user(&serial_cmd, (void __user *)arg, sizeof(serial_cmd)); - if (retval) - return -EFAULT; - - retval = get_serial_poll_byte(board, serial_cmd.pad, serial_cmd.sad, board->usec_timeout, - &serial_cmd.status_byte); - if (retval < 0) - return retval; - - retval = copy_to_user((void __user *)arg, &serial_cmd, sizeof(serial_cmd)); - if (retval) - return -EFAULT; - - return 0; -} - -static int wait_ioctl(struct gpib_file_private *file_priv, struct gpib_board *board, - unsigned long arg) -{ - struct gpib_wait_ioctl wait_cmd; - int retval; - struct gpib_descriptor *desc; - - retval = copy_from_user(&wait_cmd, (void __user *)arg, sizeof(wait_cmd)); - if (retval) - return -EFAULT; - - desc = handle_to_descriptor(file_priv, wait_cmd.handle); - if (!desc) - return -EINVAL; - - retval = ibwait(board, wait_cmd.wait_mask, wait_cmd.clear_mask, - wait_cmd.set_mask, &wait_cmd.ibsta, wait_cmd.usec_timeout, desc); - if (retval < 0) - return retval; - - retval = copy_to_user((void __user *)arg, &wait_cmd, sizeof(wait_cmd)); - if (retval) - return -EFAULT; - - return 0; -} - -static int parallel_poll_ioctl(struct gpib_board *board, unsigned long arg) -{ - u8 poll_byte; - int retval; - - retval = ibrpp(board, &poll_byte); - if (retval < 0) - return retval; - - retval = copy_to_user((void __user *)arg, &poll_byte, sizeof(poll_byte)); - if (retval) - return -EFAULT; - - return 0; -} - -static int online_ioctl(struct gpib_board *board, unsigned long arg) -{ - struct gpib_online_ioctl online_cmd; - int retval; - void __user *init_data = NULL; - - board->config.init_data = NULL; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - retval = copy_from_user(&online_cmd, (void __user *)arg, sizeof(online_cmd)); - if (retval) - return -EFAULT; - if (online_cmd.init_data_length > 0) { - board->config.init_data = vmalloc(online_cmd.init_data_length); - if (!board->config.init_data) - return -ENOMEM; - if (WARN_ON_ONCE(sizeof(init_data) > sizeof(online_cmd.init_data_ptr))) - return -EFAULT; - init_data = (void __user *)(unsigned long)(online_cmd.init_data_ptr); - retval = copy_from_user(board->config.init_data, init_data, - online_cmd.init_data_length); - if (retval) { - vfree(board->config.init_data); - return -EFAULT; - } - board->config.init_data_length = online_cmd.init_data_length; - } else { - board->config.init_data = NULL; - board->config.init_data_length = 0; - } - if (online_cmd.online) - retval = ibonline(board); - else - retval = iboffline(board); - if (board->config.init_data) { - vfree(board->config.init_data); - board->config.init_data = NULL; - board->config.init_data_length = 0; - } - return retval; -} - -static int remote_enable_ioctl(struct gpib_board *board, unsigned long arg) -{ - int enable; - int retval; - - retval = copy_from_user(&enable, (void __user *)arg, sizeof(enable)); - if (retval) - return -EFAULT; - - return ibsre(board, enable); -} - -static int take_control_ioctl(struct gpib_board *board, unsigned long arg) -{ - int synchronous; - int retval; - - retval = copy_from_user(&synchronous, (void __user *)arg, sizeof(synchronous)); - if (retval) - return -EFAULT; - - return ibcac(board, synchronous, 1); -} - -static int line_status_ioctl(struct gpib_board *board, unsigned long arg) -{ - short lines; - int retval; - - retval = iblines(board, &lines); - if (retval < 0) - return retval; - - retval = copy_to_user((void __user *)arg, &lines, sizeof(lines)); - if (retval) - return -EFAULT; - - return 0; -} - -static int pad_ioctl(struct gpib_board *board, struct gpib_file_private *file_priv, - unsigned long arg) -{ - struct gpib_pad_ioctl cmd; - int retval; - struct gpib_descriptor *desc; - - retval = copy_from_user(&cmd, (void __user *)arg, sizeof(cmd)); - if (retval) - return -EFAULT; - - desc = handle_to_descriptor(file_priv, cmd.handle); - if (!desc) - return -EINVAL; - - if (desc->is_board) { - retval = ibpad(board, cmd.pad); - if (retval < 0) - return retval; - } else { - retval = decrement_open_device_count(board, &board->device_list, desc->pad, - desc->sad); - if (retval < 0) - return retval; - - desc->pad = cmd.pad; - - retval = increment_open_device_count(board, &board->device_list, desc->pad, - desc->sad); - if (retval < 0) - return retval; - } - - return 0; -} - -static int sad_ioctl(struct gpib_board *board, struct gpib_file_private *file_priv, - unsigned long arg) -{ - struct gpib_sad_ioctl cmd; - int retval; - struct gpib_descriptor *desc; - - retval = copy_from_user(&cmd, (void __user *)arg, sizeof(cmd)); - if (retval) - return -EFAULT; - - desc = handle_to_descriptor(file_priv, cmd.handle); - if (!desc) - return -EINVAL; - - if (desc->is_board) { - retval = ibsad(board, cmd.sad); - if (retval < 0) - return retval; - } else { - retval = decrement_open_device_count(board, &board->device_list, desc->pad, - desc->sad); - if (retval < 0) - return retval; - - desc->sad = cmd.sad; - - retval = increment_open_device_count(board, &board->device_list, desc->pad, - desc->sad); - if (retval < 0) - return retval; - } - return 0; -} - -static int eos_ioctl(struct gpib_board *board, unsigned long arg) -{ - struct gpib_eos_ioctl eos_cmd; - int retval; - - retval = copy_from_user(&eos_cmd, (void __user *)arg, sizeof(eos_cmd)); - if (retval) - return -EFAULT; - - return ibeos(board, eos_cmd.eos, eos_cmd.eos_flags); -} - -static int request_service_ioctl(struct gpib_board *board, unsigned long arg) -{ - u8 status_byte; - int retval; - - retval = copy_from_user(&status_byte, (void __user *)arg, sizeof(status_byte)); - if (retval) - return -EFAULT; - - return ibrsv2(board, status_byte, status_byte & request_service_bit); -} - -static int request_service2_ioctl(struct gpib_board *board, unsigned long arg) -{ - struct gpib_request_service2 request_service2_cmd; - int retval; - - retval = copy_from_user(&request_service2_cmd, (void __user *)arg, - sizeof(struct gpib_request_service2)); - if (retval) - return -EFAULT; - - return ibrsv2(board, request_service2_cmd.status_byte, - request_service2_cmd.new_reason_for_service); -} - -static int iobase_ioctl(struct gpib_board_config *config, unsigned long arg) -{ - u64 base_addr; - int retval; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - retval = copy_from_user(&base_addr, (void __user *)arg, sizeof(base_addr)); - if (retval) - return -EFAULT; - - if (WARN_ON_ONCE(sizeof(void *) > sizeof(base_addr))) - return -EFAULT; - config->ibbase = base_addr; - - return 0; -} - -static int irq_ioctl(struct gpib_board_config *config, unsigned long arg) -{ - unsigned int irq; - int retval; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - retval = copy_from_user(&irq, (void __user *)arg, sizeof(irq)); - if (retval) - return -EFAULT; - - config->ibirq = irq; - - return 0; -} - -static int dma_ioctl(struct gpib_board_config *config, unsigned long arg) -{ - unsigned int dma_channel; - int retval; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - retval = copy_from_user(&dma_channel, (void __user *)arg, sizeof(dma_channel)); - if (retval) - return -EFAULT; - - config->ibdma = dma_channel; - - return 0; -} - -static int autospoll_ioctl(struct gpib_board *board, struct gpib_file_private *file_priv, - unsigned long arg) -{ - short enable; - int retval; - struct gpib_descriptor *desc; - - retval = copy_from_user(&enable, (void __user *)arg, sizeof(enable)); - if (retval) - return -EFAULT; - - desc = handle_to_descriptor(file_priv, 0); /* board handle is 0 */ - - if (enable) { - if (!desc->autopoll_enabled) { - board->autospollers++; - desc->autopoll_enabled = 1; - } - retval = 0; - } else { - if (desc->autopoll_enabled) { - desc->autopoll_enabled = 0; - if (board->autospollers > 0) { - board->autospollers--; - retval = 0; - } else { - dev_err(board->gpib_dev, - "tried to set number of autospollers negative\n"); - retval = -EINVAL; - } - } else { - dev_err(board->gpib_dev, "autopoll disable requested before enable\n"); - retval = -EINVAL; - } - } - return retval; -} - -static int mutex_ioctl(struct gpib_board *board, struct gpib_file_private *file_priv, - unsigned long arg) -{ - int retval, lock_mutex; - - retval = copy_from_user(&lock_mutex, (void __user *)arg, sizeof(lock_mutex)); - if (retval) - return -EFAULT; - - if (lock_mutex) { - retval = mutex_lock_interruptible(&board->user_mutex); - if (retval) - return -ERESTARTSYS; - - spin_lock(&board->locking_pid_spinlock); - board->locking_pid = current->pid; - spin_unlock(&board->locking_pid_spinlock); - - atomic_set(&file_priv->holding_mutex, 1); - - dev_dbg(board->gpib_dev, "locked board mutex\n"); - } else { - spin_lock(&board->locking_pid_spinlock); - if (current->pid != board->locking_pid) { - dev_err(board->gpib_dev, "bug! pid %i tried to release mutex held by pid %i\n", - current->pid, board->locking_pid); - spin_unlock(&board->locking_pid_spinlock); - return -EPERM; - } - board->locking_pid = 0; - spin_unlock(&board->locking_pid_spinlock); - - atomic_set(&file_priv->holding_mutex, 0); - - mutex_unlock(&board->user_mutex); - dev_dbg(board->gpib_dev, "unlocked board mutex\n"); - } - return 0; -} - -static int timeout_ioctl(struct gpib_board *board, unsigned long arg) -{ - unsigned int timeout; - int retval; - - retval = copy_from_user(&timeout, (void __user *)arg, sizeof(timeout)); - if (retval) - return -EFAULT; - - board->usec_timeout = timeout; - dev_dbg(board->gpib_dev, "timeout set to %i usec\n", timeout); - - return 0; -} - -static int ppc_ioctl(struct gpib_board *board, unsigned long arg) -{ - struct gpib_ppoll_config_ioctl cmd; - int retval; - - retval = copy_from_user(&cmd, (void __user *)arg, sizeof(cmd)); - if (retval) - return -EFAULT; - - if (cmd.set_ist) { - board->ist = 1; - board->interface->parallel_poll_response(board, board->ist); - } else if (cmd.clear_ist) { - board->ist = 0; - board->interface->parallel_poll_response(board, board->ist); - } - - if (cmd.config) { - retval = ibppc(board, cmd.config); - if (retval < 0) - return retval; - } - - return 0; -} - -static int set_local_ppoll_mode_ioctl(struct gpib_board *board, unsigned long arg) -{ - short cmd; - int retval; - - retval = copy_from_user(&cmd, (void __user *)arg, sizeof(cmd)); - if (retval) - return -EFAULT; - - if (!board->interface->local_parallel_poll_mode) - return -ENOENT; - board->local_ppoll_mode = cmd != 0; - board->interface->local_parallel_poll_mode(board, board->local_ppoll_mode); - - return 0; -} - -static int get_local_ppoll_mode_ioctl(struct gpib_board *board, unsigned long arg) -{ - short cmd; - int retval; - - cmd = board->local_ppoll_mode; - retval = copy_to_user((void __user *)arg, &cmd, sizeof(cmd)); - if (retval) - return -EFAULT; - - return 0; -} - -static int query_board_rsv_ioctl(struct gpib_board *board, unsigned long arg) -{ - int status; - int retval; - - status = board->interface->serial_poll_status(board); - - retval = copy_to_user((void __user *)arg, &status, sizeof(status)); - if (retval) - return -EFAULT; - - return 0; -} - -static int board_info_ioctl(const struct gpib_board *board, unsigned long arg) -{ - struct gpib_board_info_ioctl info = { }; - int retval; - - info.pad = board->pad; - info.sad = board->sad; - info.parallel_poll_configuration = board->parallel_poll_configuration; - info.is_system_controller = board->master; - if (board->autospollers) - info.autopolling = 1; - else - info.autopolling = 0; - info.t1_delay = board->t1_nano_sec; - info.ist = board->ist; - info.no_7_bit_eos = board->interface->no_7_bit_eos; - retval = copy_to_user((void __user *)arg, &info, sizeof(info)); - if (retval) - return -EFAULT; - - return 0; -} - -static int interface_clear_ioctl(struct gpib_board *board, unsigned long arg) -{ - unsigned int usec_duration; - int retval; - - retval = copy_from_user(&usec_duration, (void __user *)arg, sizeof(usec_duration)); - if (retval) - return -EFAULT; - - return ibsic(board, usec_duration); -} - -static int select_pci_ioctl(struct gpib_board_config *config, unsigned long arg) -{ - struct gpib_select_pci_ioctl selection; - int retval; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - retval = copy_from_user(&selection, (void __user *)arg, sizeof(selection)); - if (retval) - return -EFAULT; - - config->pci_bus = selection.pci_bus; - config->pci_slot = selection.pci_slot; - - return 0; -} - -static int select_device_path_ioctl(struct gpib_board_config *config, unsigned long arg) -{ - struct gpib_select_device_path_ioctl *selection; - int retval; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - selection = vmalloc(sizeof(struct gpib_select_device_path_ioctl)); - if (!selection) - return -ENOMEM; - - retval = copy_from_user(selection, (void __user *)arg, - sizeof(struct gpib_select_device_path_ioctl)); - if (retval) { - vfree(selection); - return -EFAULT; - } - - selection->device_path[sizeof(selection->device_path) - 1] = '\0'; - kfree(config->device_path); - config->device_path = NULL; - if (strlen(selection->device_path) > 0) - config->device_path = kstrdup(selection->device_path, GFP_KERNEL); - - vfree(selection); - return 0; -} - -unsigned int num_gpib_events(const struct gpib_event_queue *queue) -{ - return queue->num_events; -} - -static int push_gpib_event_nolock(struct gpib_board *board, short event_type) -{ - struct gpib_event_queue *queue = &board->event_queue; - struct list_head *head = &queue->event_head; - struct gpib_event *event; - static const unsigned int max_num_events = 1024; - int retval; - - if (num_gpib_events(queue) >= max_num_events) { - short lost_event; - - queue->dropped_event = 1; - retval = pop_gpib_event_nolock(board, queue, &lost_event); - if (retval < 0) - return retval; - } - - event = kmalloc(sizeof(struct gpib_event), GFP_ATOMIC); - if (!event) { - queue->dropped_event = 1; - dev_err(board->gpib_dev, "failed to allocate memory for event\n"); - return -ENOMEM; - } - - INIT_LIST_HEAD(&event->list); - event->event_type = event_type; - - list_add_tail(&event->list, head); - - queue->num_events++; - - dev_dbg(board->gpib_dev, "pushed event %i, %i in queue\n", - (int)event_type, num_gpib_events(queue)); - - return 0; -} - -// push event onto back of event queue -int push_gpib_event(struct gpib_board *board, short event_type) -{ - unsigned long flags; - int retval; - - spin_lock_irqsave(&board->event_queue.lock, flags); - retval = push_gpib_event_nolock(board, event_type); - spin_unlock_irqrestore(&board->event_queue.lock, flags); - - if (event_type == EVENT_DEV_TRG) - board->status |= DTAS; - if (event_type == EVENT_DEV_CLR) - board->status |= DCAS; - - return retval; -} -EXPORT_SYMBOL(push_gpib_event); - -static int pop_gpib_event_nolock(struct gpib_board *board, - struct gpib_event_queue *queue, short *event_type) -{ - struct list_head *head = &queue->event_head; - struct list_head *front = head->next; - struct gpib_event *event; - - if (num_gpib_events(queue) == 0) { - *event_type = EVENT_NONE; - return 0; - } - - if (front == head) - return -EIO; - - if (queue->dropped_event) { - queue->dropped_event = 0; - return -EPIPE; - } - - event = list_entry(front, struct gpib_event, list); - *event_type = event->event_type; - - list_del(front); - kfree(event); - - queue->num_events--; - - dev_dbg(board->gpib_dev, "popped event %i, %i in queue\n", - (int)*event_type, num_gpib_events(queue)); - - return 0; -} - -// pop event from front of event queue -int pop_gpib_event(struct gpib_board *board, struct gpib_event_queue *queue, short *event_type) -{ - unsigned long flags; - int retval; - - spin_lock_irqsave(&queue->lock, flags); - retval = pop_gpib_event_nolock(board, queue, event_type); - spin_unlock_irqrestore(&queue->lock, flags); - return retval; -} - -static int event_ioctl(struct gpib_board *board, unsigned long arg) -{ - short user_event; - int retval; - short event; - - retval = pop_gpib_event(board, &board->event_queue, &event); - if (retval < 0) - return retval; - - user_event = event; - - retval = copy_to_user((void __user *)arg, &user_event, sizeof(user_event)); - if (retval) - return -EFAULT; - - return 0; -} - -static int request_system_control_ioctl(struct gpib_board *board, unsigned long arg) -{ - int request_control; - int retval; - - retval = copy_from_user(&request_control, (void __user *)arg, sizeof(request_control)); - if (retval) - return -EFAULT; - - return ibrsc(board, request_control); -} - -static int t1_delay_ioctl(struct gpib_board *board, unsigned long arg) -{ - unsigned int cmd; - unsigned int delay; - int retval; - - if (!board->interface->t1_delay) - return -ENOENT; - - retval = copy_from_user(&cmd, (void __user *)arg, sizeof(cmd)); - if (retval) - return -EFAULT; - - delay = cmd; - - retval = board->interface->t1_delay(board, delay); - if (retval < 0) - return retval; - - board->t1_nano_sec = retval; - return 0; -} - -static const struct file_operations ib_fops = { - .owner = THIS_MODULE, - .llseek = NULL, - .unlocked_ioctl = &ibioctl, - .compat_ioctl = &ibioctl, - .open = &ibopen, - .release = &ibclose, -}; - -struct gpib_board board_array[GPIB_MAX_NUM_BOARDS]; - -LIST_HEAD(registered_drivers); - -void init_gpib_descriptor(struct gpib_descriptor *desc) -{ - desc->pad = 0; - desc->sad = -1; - desc->is_board = 0; - desc->autopoll_enabled = 0; - atomic_set(&desc->io_in_progress, 0); -} - -int gpib_register_driver(struct gpib_interface *interface, struct module *provider_module) -{ - struct gpib_interface_list *entry; - - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) - return -ENOMEM; - - entry->interface = interface; - entry->module = provider_module; - list_add(&entry->list, ®istered_drivers); - - return 0; -} -EXPORT_SYMBOL(gpib_register_driver); - -void gpib_unregister_driver(struct gpib_interface *interface) -{ - int i; - struct list_head *list_ptr; - - for (i = 0; i < GPIB_MAX_NUM_BOARDS; i++) { - struct gpib_board *board = &board_array[i]; - - if (board->interface == interface) { - if (board->use_count > 0) - pr_warn("gpib: Warning: deregistered interface %s in use\n", - interface->name); - iboffline(board); - board->interface = NULL; - } - } - for (list_ptr = registered_drivers.next; list_ptr != ®istered_drivers;) { - struct gpib_interface_list *entry; - - entry = list_entry(list_ptr, struct gpib_interface_list, list); - list_ptr = list_ptr->next; - if (entry->interface == interface) { - list_del(&entry->list); - kfree(entry); - } - } -} -EXPORT_SYMBOL(gpib_unregister_driver); - -static void init_gpib_board_config(struct gpib_board_config *config) -{ - memset(config, 0, sizeof(struct gpib_board_config)); - config->pci_bus = -1; - config->pci_slot = -1; -} - -void init_gpib_board(struct gpib_board *board) -{ - board->interface = NULL; - board->provider_module = NULL; - board->buffer = NULL; - board->buffer_length = 0; - board->status = 0; - init_waitqueue_head(&board->wait); - mutex_init(&board->user_mutex); - mutex_init(&board->big_gpib_mutex); - board->locking_pid = 0; - spin_lock_init(&board->locking_pid_spinlock); - spin_lock_init(&board->spinlock); - timer_setup(&board->timer, NULL, 0); - board->dev = NULL; - board->gpib_dev = NULL; - init_gpib_board_config(&board->config); - board->private_data = NULL; - board->use_count = 0; - INIT_LIST_HEAD(&board->device_list); - board->pad = 0; - board->sad = -1; - board->usec_timeout = 3000000; - board->parallel_poll_configuration = 0; - board->online = 0; - board->autospollers = 0; - board->autospoll_task = NULL; - init_event_queue(&board->event_queue); - board->minor = -1; - init_gpib_pseudo_irq(&board->pseudo_irq); - board->master = 1; - atomic_set(&board->stuck_srq, 0); - board->local_ppoll_mode = 0; -} - -int gpib_allocate_board(struct gpib_board *board) -{ - if (!board->buffer) { - board->buffer_length = 0x4000; - board->buffer = vmalloc(board->buffer_length); - if (!board->buffer) { - board->buffer_length = 0; - return -ENOMEM; - } - } - return 0; -} - -void gpib_deallocate_board(struct gpib_board *board) -{ - short dummy; - - if (board->buffer) { - vfree(board->buffer); - board->buffer = NULL; - board->buffer_length = 0; - } - while (num_gpib_events(&board->event_queue)) - pop_gpib_event(board, &board->event_queue, &dummy); -} - -static void init_board_array(struct gpib_board *board_array, unsigned int length) -{ - int i; - - for (i = 0; i < length; i++) { - init_gpib_board(&board_array[i]); - board_array[i].minor = i; - } -} - -void init_gpib_status_queue(struct gpib_status_queue *device) -{ - INIT_LIST_HEAD(&device->list); - INIT_LIST_HEAD(&device->status_bytes); - device->num_status_bytes = 0; - device->reference_count = 0; - device->dropped_byte = 0; -} - -static struct class *gpib_class; - -static int __init gpib_common_init_module(void) -{ - int i; - - pr_info("GPIB core driver\n"); - init_board_array(board_array, GPIB_MAX_NUM_BOARDS); - if (register_chrdev(GPIB_CODE, "gpib", &ib_fops)) { - pr_err("gpib: can't get major %d\n", GPIB_CODE); - return -EIO; - } - gpib_class = class_create("gpib_common"); - if (IS_ERR(gpib_class)) { - pr_err("gpib: failed to create gpib class\n"); - unregister_chrdev(GPIB_CODE, "gpib"); - return PTR_ERR(gpib_class); - } - for (i = 0; i < GPIB_MAX_NUM_BOARDS; ++i) - board_array[i].gpib_dev = device_create(gpib_class, NULL, - MKDEV(GPIB_CODE, i), NULL, "gpib%i", i); - - return 0; -} - -static void __exit gpib_common_exit_module(void) -{ - int i; - - for (i = 0; i < GPIB_MAX_NUM_BOARDS; ++i) - device_destroy(gpib_class, MKDEV(GPIB_CODE, i)); - - class_destroy(gpib_class); - unregister_chrdev(GPIB_CODE, "gpib"); -} - -int gpib_match_device_path(struct device *dev, const char *device_path_in) -{ - if (device_path_in) { - char *device_path; - - device_path = kobject_get_path(&dev->kobj, GFP_KERNEL); - if (!device_path) { - dev_err(dev, "kobject_get_path returned NULL."); - return 0; - } - if (strcmp(device_path_in, device_path) != 0) { - kfree(device_path); - return 0; - } - kfree(device_path); - } - return 1; -} -EXPORT_SYMBOL(gpib_match_device_path); - -struct pci_dev *gpib_pci_get_device(const struct gpib_board_config *config, unsigned int vendor_id, - unsigned int device_id, struct pci_dev *from) -{ - struct pci_dev *pci_device = from; - - while ((pci_device = pci_get_device(vendor_id, device_id, pci_device))) { - if (config->pci_bus >= 0 && config->pci_bus != pci_device->bus->number) - continue; - if (config->pci_slot >= 0 && config->pci_slot != - PCI_SLOT(pci_device->devfn)) - continue; - if (gpib_match_device_path(&pci_device->dev, config->device_path) == 0) - continue; - return pci_device; - } - return NULL; -} -EXPORT_SYMBOL(gpib_pci_get_device); - -struct pci_dev *gpib_pci_get_subsys(const struct gpib_board_config *config, unsigned int vendor_id, - unsigned int device_id, unsigned int ss_vendor, - unsigned int ss_device, - struct pci_dev *from) -{ - struct pci_dev *pci_device = from; - - while ((pci_device = pci_get_subsys(vendor_id, device_id, - ss_vendor, ss_device, pci_device))) { - if (config->pci_bus >= 0 && config->pci_bus != pci_device->bus->number) - continue; - if (config->pci_slot >= 0 && config->pci_slot != - PCI_SLOT(pci_device->devfn)) - continue; - if (gpib_match_device_path(&pci_device->dev, config->device_path) == 0) - continue; - return pci_device; - } - return NULL; -} -EXPORT_SYMBOL(gpib_pci_get_subsys); - -module_init(gpib_common_init_module); -module_exit(gpib_common_exit_module); - diff --git a/drivers/staging/gpib/common/iblib.c b/drivers/staging/gpib/common/iblib.c deleted file mode 100644 index 7cbb6a467177..000000000000 --- a/drivers/staging/gpib/common/iblib.c +++ /dev/null @@ -1,717 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * copyright : (C) 2001, 2002 by Frank Mori Hess - ***************************************************************************/ - -#define dev_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "ibsys.h" -#include <linux/delay.h> -#include <linux/kthread.h> -#include <linux/vmalloc.h> - -/* - * IBCAC - * Return to the controller active state from the - * controller standby state, i.e., turn ATN on. Note - * that in order to enter the controller active state - * from the controller idle state, ibsic must be called. - * If sync is non-zero, attempt to take control synchronously. - * If fallback_to_async is non-zero, try to take control asynchronously - * if synchronous attempt fails. - */ -int ibcac(struct gpib_board *board, int sync, int fallback_to_async) -{ - int status = ibstatus(board); - int retval; - - if ((status & CIC) == 0) - return -EINVAL; - - if (status & ATN) - return 0; - - if (sync && (status & LACS) == 0) - /* - * tcs (take control synchronously) can only possibly work when - * controller is listener. Error code also needs to be -ETIMEDOUT - * or it will giveout without doing fallback. - */ - retval = -ETIMEDOUT; - else - retval = board->interface->take_control(board, sync); - - if (retval < 0 && fallback_to_async) { - if (sync && retval == -ETIMEDOUT) - retval = board->interface->take_control(board, 0); - } - board->interface->update_status(board, 0); - - return retval; -} - -/* - * After ATN is asserted, it should cause any connected devices - * to start listening for command bytes and leave acceptor idle state. - * So if ATN is asserted and neither NDAC or NRFD are asserted, - * then there are no devices and ibcmd should error out immediately. - * Some gpib hardware sees itself asserting NDAC/NRFD when it - * is controller in charge, in which case this check will - * do nothing useful (but shouldn't cause any harm either). - * Drivers that don't need this check (ni_usb for example) may - * set the skip_check_for_command_acceptors flag in their - * gpib_interface_struct to avoid useless overhead. - */ -static int check_for_command_acceptors(struct gpib_board *board) -{ - int lines; - - if (board->interface->skip_check_for_command_acceptors) - return 0; - if (!board->interface->line_status) - return 0; - - udelay(2); // allow time for devices to respond to ATN if it was just asserted - - lines = board->interface->line_status(board); - if (lines < 0) - return lines; - - if ((lines & VALID_NRFD) && (lines & VALID_NDAC)) { - if ((lines & BUS_NRFD) == 0 && (lines & BUS_NDAC) == 0) - return -ENOTCONN; - } - - return 0; -} - -/* - * IBCMD - * Write cnt command bytes from buf to the GPIB. The - * command operation terminates only on I/O complete. - * - * NOTE: - * 1. Prior to beginning the command, the interface is - * placed in the controller active state. - * 2. Before calling ibcmd for the first time, ibsic - * must be called to initialize the GPIB and enable - * the interface to leave the controller idle state. - */ -int ibcmd(struct gpib_board *board, u8 *buf, size_t length, size_t *bytes_written) -{ - ssize_t ret = 0; - int status; - - *bytes_written = 0; - - status = ibstatus(board); - - if ((status & CIC) == 0) - return -EINVAL; - - os_start_timer(board, board->usec_timeout); - - ret = ibcac(board, 1, 1); - if (ret == 0) { - ret = check_for_command_acceptors(board); - if (ret == 0) - ret = board->interface->command(board, buf, length, bytes_written); - } - - os_remove_timer(board); - - if (io_timed_out(board)) - ret = -ETIMEDOUT; - - return ret; -} - -/* - * IBGTS - * Go to the controller standby state from the controller - * active state, i.e., turn ATN off. - */ - -int ibgts(struct gpib_board *board) -{ - int status = ibstatus(board); - int retval; - - if ((status & CIC) == 0) - return -EINVAL; - - retval = board->interface->go_to_standby(board); /* go to standby */ - - board->interface->update_status(board, 0); - - return retval; -} - -static int autospoll_wait_should_wake_up(struct gpib_board *board) -{ - int retval; - - mutex_lock(&board->big_gpib_mutex); - - retval = board->master && board->autospollers > 0 && - !atomic_read(&board->stuck_srq) && - test_and_clear_bit(SRQI_NUM, &board->status); - - mutex_unlock(&board->big_gpib_mutex); - return retval; -} - -static int autospoll_thread(void *board_void) -{ - struct gpib_board *board = board_void; - int retval = 0; - - dev_dbg(board->gpib_dev, "entering autospoll thread\n"); - - while (1) { - wait_event_interruptible(board->wait, - kthread_should_stop() || - autospoll_wait_should_wake_up(board)); - dev_dbg(board->gpib_dev, "autospoll wait satisfied\n"); - if (kthread_should_stop()) - break; - - mutex_lock(&board->big_gpib_mutex); - /* make sure we are still good after we have lock */ - if (board->autospollers <= 0 || board->master == 0) { - mutex_unlock(&board->big_gpib_mutex); - continue; - } - mutex_unlock(&board->big_gpib_mutex); - - if (try_module_get(board->provider_module)) { - retval = autopoll_all_devices(board); - module_put(board->provider_module); - } else { - dev_err(board->gpib_dev, "try_module_get() failed!\n"); - } - if (retval <= 0) { - dev_err(board->gpib_dev, "stuck SRQ\n"); - - atomic_set(&board->stuck_srq, 1); // XXX could be better - set_bit(SRQI_NUM, &board->status); - } - } - return retval; -} - -int ibonline(struct gpib_board *board) -{ - int retval; - - if (board->online) - return -EBUSY; - if (!board->interface) - return -ENODEV; - retval = gpib_allocate_board(board); - if (retval < 0) - return retval; - - board->dev = NULL; - board->local_ppoll_mode = 0; - retval = board->interface->attach(board, &board->config); - if (retval < 0) { - board->interface->detach(board); - return retval; - } - /* - * nios2nommu on 2.6.11 uclinux kernel has weird problems - * with autospoll thread causing huge slowdowns - */ -#ifndef CONFIG_NIOS2 - board->autospoll_task = kthread_run(&autospoll_thread, board, - "gpib%d_autospoll_kthread", board->minor); - retval = IS_ERR(board->autospoll_task); - if (retval) { - dev_err(board->gpib_dev, "failed to create autospoll thread\n"); - board->interface->detach(board); - return retval; - } -#endif - board->online = 1; - dev_dbg(board->gpib_dev, "board online\n"); - - return 0; -} - -/* XXX need to make sure board is generally not in use (grab board lock?) */ -int iboffline(struct gpib_board *board) -{ - int retval; - - if (board->online == 0) - return 0; - if (!board->interface) - return -ENODEV; - - if (board->autospoll_task && !IS_ERR(board->autospoll_task)) { - retval = kthread_stop(board->autospoll_task); - if (retval) - dev_err(board->gpib_dev, "kthread_stop returned %i\n", retval); - board->autospoll_task = NULL; - } - - board->interface->detach(board); - gpib_deallocate_board(board); - board->online = 0; - dev_dbg(board->gpib_dev, "board offline\n"); - - return 0; -} - -/* - * IBLINES - * Poll the GPIB control lines and return their status in buf. - * - * LSB (bits 0-7) - VALID lines mask (lines that can be monitored). - * Next LSB (bits 8-15) - STATUS lines mask (lines that are currently set). - * - */ -int iblines(const struct gpib_board *board, short *lines) -{ - int retval; - - *lines = 0; - if (!board->interface->line_status) - return 0; - retval = board->interface->line_status(board); - if (retval < 0) - return retval; - *lines = retval; - return 0; -} - -/* - * IBRD - * Read up to 'length' bytes of data from the GPIB into buf. End - * on detection of END (EOI and or EOS) and set 'end_flag'. - * - * NOTE: - * 1. The interface is placed in the controller standby - * state prior to beginning the read. - * 2. Prior to calling ibrd, the intended devices as well - * as the interface board itself must be addressed by - * calling ibcmd. - */ - -int ibrd(struct gpib_board *board, u8 *buf, size_t length, int *end_flag, size_t *nbytes) -{ - ssize_t ret = 0; - int retval; - size_t bytes_read; - - *nbytes = 0; - *end_flag = 0; - if (length == 0) - return 0; - - if (board->master) { - retval = ibgts(board); - if (retval < 0) - return retval; - } - /* - * XXX resetting timer here could cause timeouts take longer than they should, - * since read_ioctl calls this - * function in a loop, there is probably a similar problem with writes/commands - */ - os_start_timer(board, board->usec_timeout); - - do { - ret = board->interface->read(board, buf, length - *nbytes, end_flag, &bytes_read); - if (ret < 0) - goto ibrd_out; - - buf += bytes_read; - *nbytes += bytes_read; - if (need_resched()) - schedule(); - } while (ret == 0 && *nbytes > 0 && *nbytes < length && *end_flag == 0); -ibrd_out: - os_remove_timer(board); - - return ret; -} - -/* - * IBRPP - * Conduct a parallel poll and return the byte in buf. - * - * NOTE: - * 1. Prior to conducting the poll the interface is placed - * in the controller active state. - */ -int ibrpp(struct gpib_board *board, u8 *result) -{ - int retval = 0; - - os_start_timer(board, board->usec_timeout); - retval = ibcac(board, 1, 1); - if (retval) - return -1; - - retval = board->interface->parallel_poll(board, result); - - os_remove_timer(board); - return retval; -} - -int ibppc(struct gpib_board *board, u8 configuration) -{ - configuration &= 0x1f; - board->interface->parallel_poll_configure(board, configuration); - board->parallel_poll_configuration = configuration; - - return 0; -} - -int ibrsv2(struct gpib_board *board, u8 status_byte, int new_reason_for_service) -{ - int board_status = ibstatus(board); - const unsigned int MSS = status_byte & request_service_bit; - - if ((board_status & CIC)) - return -EINVAL; - - if (MSS == 0 && new_reason_for_service) - return -EINVAL; - - if (board->interface->serial_poll_response2) { - board->interface->serial_poll_response2(board, status_byte, new_reason_for_service); - // fall back on simpler serial_poll_response if the behavior would be the same - } else if (board->interface->serial_poll_response && - (MSS == 0 || (MSS && new_reason_for_service))) { - board->interface->serial_poll_response(board, status_byte); - } else { - return -EOPNOTSUPP; - } - - return 0; -} - -/* - * IBSIC - * Send IFC for at least 100 microseconds. - * - * NOTE: - * 1. Ibsic must be called prior to the first call to - * ibcmd in order to initialize the bus and enable the - * interface to leave the controller idle state. - */ -int ibsic(struct gpib_board *board, unsigned int usec_duration) -{ - if (board->master == 0) - return -EINVAL; - - if (usec_duration < 100) - usec_duration = 100; - if (usec_duration > 1000) - usec_duration = 1000; - - dev_dbg(board->gpib_dev, "sending interface clear, delay = %ius\n", usec_duration); - board->interface->interface_clear(board, 1); - udelay(usec_duration); - board->interface->interface_clear(board, 0); - - return 0; -} - -int ibrsc(struct gpib_board *board, int request_control) -{ - int retval; - - if (!board->interface->request_system_control) - return -EPERM; - - retval = board->interface->request_system_control(board, request_control); - - if (retval) - return retval; - - board->master = request_control != 0; - - return 0; -} - -/* - * IBSRE - * Send REN true if v is non-zero or false if v is zero. - */ -int ibsre(struct gpib_board *board, int enable) -{ - if (board->master == 0) - return -EINVAL; - - board->interface->remote_enable(board, enable); /* set or clear REN */ - if (!enable) - usleep_range(100, 150); - - return 0; -} - -/* - * IBPAD - * change the GPIB address of the interface board. The address - * must be 0 through 30. ibonl resets the address to PAD. - */ -int ibpad(struct gpib_board *board, unsigned int addr) -{ - if (addr > MAX_GPIB_PRIMARY_ADDRESS) - return -EINVAL; - - board->pad = addr; - if (board->online) - board->interface->primary_address(board, board->pad); - dev_dbg(board->gpib_dev, "set primary addr to %i\n", board->pad); - return 0; -} - -/* - * IBSAD - * change the secondary GPIB address of the interface board. - * The address must be 0 through 30, or negative disables. ibonl resets the - * address to SAD. - */ -int ibsad(struct gpib_board *board, int addr) -{ - if (addr > MAX_GPIB_SECONDARY_ADDRESS) - return -EINVAL; - board->sad = addr; - if (board->online) { - if (board->sad >= 0) - board->interface->secondary_address(board, board->sad, 1); - else - board->interface->secondary_address(board, 0, 0); - } - dev_dbg(board->gpib_dev, "set secondary addr to %i\n", board->sad); - - return 0; -} - -/* - * IBEOS - * Set the end-of-string modes for I/O operations to v. - * - */ -int ibeos(struct gpib_board *board, int eos, int eosflags) -{ - int retval; - - if (eosflags & ~EOS_MASK) - return -EINVAL; - if (eosflags & REOS) { - retval = board->interface->enable_eos(board, eos, eosflags & BIN); - } else { - board->interface->disable_eos(board); - retval = 0; - } - return retval; -} - -int ibstatus(struct gpib_board *board) -{ - return general_ibstatus(board, NULL, 0, 0, NULL); -} - -int general_ibstatus(struct gpib_board *board, const struct gpib_status_queue *device, - int clear_mask, int set_mask, struct gpib_descriptor *desc) -{ - int status = 0; - short line_status; - - if (board->private_data) { - status = board->interface->update_status(board, clear_mask); - /* - * XXX should probably stop having drivers use TIMO bit in - * board->status to avoid confusion - */ - status &= ~TIMO; - /* get real SRQI status if we can */ - if (iblines(board, &line_status) == 0) { - if ((line_status & VALID_SRQ)) { - if ((line_status & BUS_SRQ)) - status |= SRQI; - else - status &= ~SRQI; - } - } - } - if (device) - if (num_status_bytes(device)) - status |= RQS; - - if (desc) { - if (set_mask & CMPL) - atomic_set(&desc->io_in_progress, 0); - else if (clear_mask & CMPL) - atomic_set(&desc->io_in_progress, 1); - - if (atomic_read(&desc->io_in_progress)) - status &= ~CMPL; - else - status |= CMPL; - } - if (num_gpib_events(&board->event_queue)) - status |= EVENT; - else - status &= ~EVENT; - - return status; -} - -struct wait_info { - struct gpib_board *board; - struct timer_list timer; - int timed_out; - unsigned long usec_timeout; -}; - -static void wait_timeout(struct timer_list *t) -{ - struct wait_info *winfo = timer_container_of(winfo, t, timer); - - winfo->timed_out = 1; - wake_up_interruptible(&winfo->board->wait); -} - -static void init_wait_info(struct wait_info *winfo) -{ - winfo->board = NULL; - winfo->timed_out = 0; - timer_setup_on_stack(&winfo->timer, wait_timeout, 0); -} - -static int wait_satisfied(struct wait_info *winfo, struct gpib_status_queue *status_queue, - int wait_mask, int *status, struct gpib_descriptor *desc) -{ - struct gpib_board *board = winfo->board; - int temp_status; - - if (mutex_lock_interruptible(&board->big_gpib_mutex)) - return -ERESTARTSYS; - - temp_status = general_ibstatus(board, status_queue, 0, 0, desc); - - mutex_unlock(&board->big_gpib_mutex); - - if (winfo->timed_out) - temp_status |= TIMO; - else - temp_status &= ~TIMO; - if (wait_mask & temp_status) { - *status = temp_status; - return 1; - } -// XXX does wait for END work? - return 0; -} - -/* install timer interrupt handler */ -static void start_wait_timer(struct wait_info *winfo) -/* Starts the timeout task */ -{ - winfo->timed_out = 0; - - if (winfo->usec_timeout > 0) - mod_timer(&winfo->timer, jiffies + usec_to_jiffies(winfo->usec_timeout)); -} - -static void remove_wait_timer(struct wait_info *winfo) -{ - timer_delete_sync(&winfo->timer); - timer_destroy_on_stack(&winfo->timer); -} - -/* - * IBWAIT - * Check or wait for a GPIB event to occur. The mask argument - * is a bit vector corresponding to the status bit vector. It - * has a bit set for each condition which can terminate the wait - * If the mask is 0 then - * no condition is waited for. - */ -int ibwait(struct gpib_board *board, int wait_mask, int clear_mask, int set_mask, - int *status, unsigned long usec_timeout, struct gpib_descriptor *desc) -{ - int retval = 0; - struct gpib_status_queue *status_queue; - struct wait_info winfo; - - if (desc->is_board) - status_queue = NULL; - else - status_queue = get_gpib_status_queue(board, desc->pad, desc->sad); - - if (wait_mask == 0) { - *status = general_ibstatus(board, status_queue, clear_mask, set_mask, desc); - return 0; - } - - mutex_unlock(&board->big_gpib_mutex); - - init_wait_info(&winfo); - winfo.board = board; - winfo.usec_timeout = usec_timeout; - start_wait_timer(&winfo); - - if (wait_event_interruptible(board->wait, wait_satisfied(&winfo, status_queue, - wait_mask, status, desc))) { - dev_dbg(board->gpib_dev, "wait interrupted\n"); - retval = -ERESTARTSYS; - } - remove_wait_timer(&winfo); - - if (retval) - return retval; - if (mutex_lock_interruptible(&board->big_gpib_mutex)) - return -ERESTARTSYS; - - /* make sure we only clear status bits that we are reporting */ - if (*status & clear_mask || set_mask) - general_ibstatus(board, status_queue, *status & clear_mask, set_mask, NULL); - - return 0; -} - -/* - * IBWRT - * Write cnt bytes of data from buf to the GPIB. The write - * operation terminates only on I/O complete. - * - * NOTE: - * 1. Prior to beginning the write, the interface is - * placed in the controller standby state. - * 2. Prior to calling ibwrt, the intended devices as - * well as the interface board itself must be - * addressed by calling ibcmd. - */ -int ibwrt(struct gpib_board *board, u8 *buf, size_t cnt, int send_eoi, size_t *bytes_written) -{ - int ret = 0; - int retval; - - if (cnt == 0) - return 0; - - if (board->master) { - retval = ibgts(board); - if (retval < 0) - return retval; - } - os_start_timer(board, board->usec_timeout); - ret = board->interface->write(board, buf, cnt, send_eoi, bytes_written); - - if (io_timed_out(board)) - ret = -ETIMEDOUT; - - os_remove_timer(board); - - return ret; -} - diff --git a/drivers/staging/gpib/common/ibsys.h b/drivers/staging/gpib/common/ibsys.h deleted file mode 100644 index e5a148f513a8..000000000000 --- a/drivers/staging/gpib/common/ibsys.h +++ /dev/null @@ -1,34 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#include "gpibP.h" - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/major.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/timer.h> - -#include <linux/io.h> -#include <linux/uaccess.h> -#include <asm/irq.h> -#include <asm/dma.h> - -#define MAX_GPIB_PRIMARY_ADDRESS 30 -#define MAX_GPIB_SECONDARY_ADDRESS 31 - -int gpib_allocate_board(struct gpib_board *board); -void gpib_deallocate_board(struct gpib_board *board); - -unsigned int num_status_bytes(const struct gpib_status_queue *dev); -int push_status_byte(struct gpib_board *board, struct gpib_status_queue *device, - u8 poll_byte); -int pop_status_byte(struct gpib_board *board, struct gpib_status_queue *device, - u8 *poll_byte); -struct gpib_status_queue *get_gpib_status_queue(struct gpib_board *board, - unsigned int pad, int sad); -int get_serial_poll_byte(struct gpib_board *board, unsigned int pad, int sad, - unsigned int usec_timeout, u8 *poll_byte); -int autopoll_all_devices(struct gpib_board *board); diff --git a/drivers/staging/gpib/eastwood/Makefile b/drivers/staging/gpib/eastwood/Makefile deleted file mode 100644 index 384825195f77..000000000000 --- a/drivers/staging/gpib/eastwood/Makefile +++ /dev/null @@ -1,3 +0,0 @@ - -obj-$(CONFIG_GPIB_FLUKE) += fluke_gpib.o - diff --git a/drivers/staging/gpib/eastwood/fluke_gpib.c b/drivers/staging/gpib/eastwood/fluke_gpib.c deleted file mode 100644 index 3ae848e3f738..000000000000 --- a/drivers/staging/gpib/eastwood/fluke_gpib.c +++ /dev/null @@ -1,1180 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * GPIB Driver for Fluke cda devices. Basically, its a driver for a (bugfixed) - * cb7210 connected to channel 0 of a pl330 dma controller. - * Author: Frank Mori Hess <fmh6jj@gmail.com> - * copyright: (C) 2006, 2010, 2015 Fluke Corporation - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define DRV_NAME KBUILD_MODNAME - -#include "fluke_gpib.h" - -#include "gpibP.h" -#include <linux/dma-mapping.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <linux/mod_devicetable.h> -#include <linux/platform_device.h> -#include <linux/slab.h> - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB Driver for Fluke cda devices"); - -static int fluke_attach_holdoff_all(struct gpib_board *board, - const struct gpib_board_config *config); -static int fluke_attach_holdoff_end(struct gpib_board *board, - const struct gpib_board_config *config); -static void fluke_detach(struct gpib_board *board); -static int fluke_config_dma(struct gpib_board *board, int output); -static irqreturn_t fluke_gpib_internal_interrupt(struct gpib_board *board); - -static struct platform_device *fluke_gpib_pdev; - -static u8 fluke_locking_read_byte(struct nec7210_priv *nec_priv, unsigned int register_number) -{ - u8 retval; - unsigned long flags; - - spin_lock_irqsave(&nec_priv->register_page_lock, flags); - retval = fluke_read_byte_nolock(nec_priv, register_number); - spin_unlock_irqrestore(&nec_priv->register_page_lock, flags); - return retval; -} - -static void fluke_locking_write_byte(struct nec7210_priv *nec_priv, u8 byte, - unsigned int register_number) -{ - unsigned long flags; - - spin_lock_irqsave(&nec_priv->register_page_lock, flags); - fluke_write_byte_nolock(nec_priv, byte, register_number); - spin_unlock_irqrestore(&nec_priv->register_page_lock, flags); -} - -// wrappers for interface functions -static int fluke_read(struct gpib_board *board, u8 *buffer, size_t length, int *end, - size_t *bytes_read) -{ - struct fluke_priv *priv = board->private_data; - - return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); -} - -static int fluke_write(struct gpib_board *board, u8 *buffer, size_t length, - int send_eoi, size_t *bytes_written) -{ - struct fluke_priv *priv = board->private_data; - - return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); -} - -static int fluke_command(struct gpib_board *board, u8 *buffer, - size_t length, size_t *bytes_written) -{ - struct fluke_priv *priv = board->private_data; - - return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); -} - -static int fluke_take_control(struct gpib_board *board, int synchronous) -{ - struct fluke_priv *priv = board->private_data; - - return nec7210_take_control(board, &priv->nec7210_priv, synchronous); -} - -static int fluke_go_to_standby(struct gpib_board *board) -{ - struct fluke_priv *priv = board->private_data; - - return nec7210_go_to_standby(board, &priv->nec7210_priv); -} - -static int fluke_request_system_control(struct gpib_board *board, int request_control) -{ - struct fluke_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - - return nec7210_request_system_control(board, nec_priv, request_control); -} - -static void fluke_interface_clear(struct gpib_board *board, int assert) -{ - struct fluke_priv *priv = board->private_data; - - nec7210_interface_clear(board, &priv->nec7210_priv, assert); -} - -static void fluke_remote_enable(struct gpib_board *board, int enable) -{ - struct fluke_priv *priv = board->private_data; - - nec7210_remote_enable(board, &priv->nec7210_priv, enable); -} - -static int fluke_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits) -{ - struct fluke_priv *priv = board->private_data; - - return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); -} - -static void fluke_disable_eos(struct gpib_board *board) -{ - struct fluke_priv *priv = board->private_data; - - nec7210_disable_eos(board, &priv->nec7210_priv); -} - -static unsigned int fluke_update_status(struct gpib_board *board, unsigned int clear_mask) -{ - struct fluke_priv *priv = board->private_data; - - return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); -} - -static int fluke_primary_address(struct gpib_board *board, unsigned int address) -{ - struct fluke_priv *priv = board->private_data; - - return nec7210_primary_address(board, &priv->nec7210_priv, address); -} - -static int fluke_secondary_address(struct gpib_board *board, unsigned int address, int enable) -{ - struct fluke_priv *priv = board->private_data; - - return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); -} - -static int fluke_parallel_poll(struct gpib_board *board, u8 *result) -{ - struct fluke_priv *priv = board->private_data; - - return nec7210_parallel_poll(board, &priv->nec7210_priv, result); -} - -static void fluke_parallel_poll_configure(struct gpib_board *board, u8 configuration) -{ - struct fluke_priv *priv = board->private_data; - - nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration); -} - -static void fluke_parallel_poll_response(struct gpib_board *board, int ist) -{ - struct fluke_priv *priv = board->private_data; - - nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); -} - -static void fluke_serial_poll_response(struct gpib_board *board, u8 status) -{ - struct fluke_priv *priv = board->private_data; - - nec7210_serial_poll_response(board, &priv->nec7210_priv, status); -} - -static u8 fluke_serial_poll_status(struct gpib_board *board) -{ - struct fluke_priv *priv = board->private_data; - - return nec7210_serial_poll_status(board, &priv->nec7210_priv); -} - -static void fluke_return_to_local(struct gpib_board *board) -{ - struct fluke_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - - write_byte(nec_priv, AUX_RTL2, AUXMR); - udelay(1); - write_byte(nec_priv, AUX_RTL, AUXMR); -} - -static int fluke_line_status(const struct gpib_board *board) -{ - int status = VALID_ALL; - int bsr_bits; - struct fluke_priv *e_priv; - - e_priv = board->private_data; - - bsr_bits = fluke_paged_read_byte(e_priv, BUS_STATUS, BUS_STATUS_PAGE); - - if ((bsr_bits & BSR_REN_BIT) == 0) - status |= BUS_REN; - if ((bsr_bits & BSR_IFC_BIT) == 0) - status |= BUS_IFC; - if ((bsr_bits & BSR_SRQ_BIT) == 0) - status |= BUS_SRQ; - if ((bsr_bits & BSR_EOI_BIT) == 0) - status |= BUS_EOI; - if ((bsr_bits & BSR_NRFD_BIT) == 0) - status |= BUS_NRFD; - if ((bsr_bits & BSR_NDAC_BIT) == 0) - status |= BUS_NDAC; - if ((bsr_bits & BSR_DAV_BIT) == 0) - status |= BUS_DAV; - if ((bsr_bits & BSR_ATN_BIT) == 0) - status |= BUS_ATN; - - return status; -} - -static int fluke_t1_delay(struct gpib_board *board, unsigned int nano_sec) -{ - struct fluke_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - unsigned int retval; - - retval = nec7210_t1_delay(board, nec_priv, nano_sec); - - if (nano_sec <= 350) { - write_byte(nec_priv, AUX_HI_SPEED, AUXMR); - retval = 350; - } else { - write_byte(nec_priv, AUX_LO_SPEED, AUXMR); - } - return retval; -} - -static int lacs_or_read_ready(struct gpib_board *board) -{ - const struct fluke_priv *e_priv = board->private_data; - const struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - unsigned long flags; - int retval; - - spin_lock_irqsave(&board->spinlock, flags); - retval = test_bit(LACS_NUM, &board->status) || test_bit(READ_READY_BN, &nec_priv->state); - spin_unlock_irqrestore(&board->spinlock, flags); - return retval; -} - -/* - * Wait until it is possible for a read to do something useful. This - * is not essential, it only exists to prevent RFD holdoff from being released pointlessly. - */ -static int wait_for_read(struct gpib_board *board) -{ - struct fluke_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - int retval = 0; - - if (wait_event_interruptible(board->wait, - lacs_or_read_ready(board) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - return retval; -} - -/* - * Check if the SH state machine is in SGNS. We check twice since there is a very small chance - * we could be blowing through SGNS from SIDS to SDYS if there is already a - * byte available in the handshake state machine. We are interested - * in the case where the handshake is stuck in SGNS due to no byte being - * available to the chip (and thus we can be confident a dma transfer will - * result in at least one byte making it into the chip). This matters - * because we want to be confident before sending a "send eoi" auxilary - * command that we will be able to also put the associated data byte - * in the chip before any potential timeout. - */ -static int source_handshake_is_sgns(struct fluke_priv *e_priv) -{ - int i; - - for (i = 0; i < 2; ++i) { - if ((fluke_paged_read_byte(e_priv, STATE1_REG, STATE1_PAGE) & - SOURCE_HANDSHAKE_MASK) != SOURCE_HANDSHAKE_SGNS_BITS) { - return 0; - } - } - return 1; -} - -static int source_handshake_is_sids_or_sgns(struct fluke_priv *e_priv) -{ - unsigned int source_handshake_bits; - - source_handshake_bits = fluke_paged_read_byte(e_priv, STATE1_REG, STATE1_PAGE) & - SOURCE_HANDSHAKE_MASK; - - return (source_handshake_bits == SOURCE_HANDSHAKE_SGNS_BITS) || - (source_handshake_bits == SOURCE_HANDSHAKE_SIDS_BITS); -} - -/* - * Wait until the gpib chip is ready to accept a data out byte. - * If the chip is SGNS it is probably waiting for a a byte to - * be written to it. - */ -static int wait_for_data_out_ready(struct gpib_board *board) -{ - struct fluke_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - int retval = 0; - - if (wait_event_interruptible(board->wait, - (test_bit(TACS_NUM, &board->status) && - source_handshake_is_sgns(e_priv)) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - return retval; -} - -static int wait_for_sids_or_sgns(struct gpib_board *board) -{ - struct fluke_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - int retval = 0; - - if (wait_event_interruptible(board->wait, - source_handshake_is_sids_or_sgns(e_priv) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - return retval; -} - -static void fluke_dma_callback(void *arg) -{ - struct gpib_board *board = arg; - struct fluke_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - unsigned long flags; - - spin_lock_irqsave(&board->spinlock, flags); - - nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, HR_DOIE | HR_DIIE); - wake_up_interruptible(&board->wait); - - fluke_gpib_internal_interrupt(board); - clear_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state); - clear_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state); - - spin_unlock_irqrestore(&board->spinlock, flags); -} - -static int fluke_dma_write(struct gpib_board *board, u8 *buffer, size_t length, - size_t *bytes_written) -{ - struct fluke_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - unsigned long flags; - int retval = 0; - dma_addr_t address; - struct dma_async_tx_descriptor *tx_desc; - - *bytes_written = 0; - - if (WARN_ON_ONCE(length > e_priv->dma_buffer_size)) - return -EFAULT; - dmaengine_terminate_all(e_priv->dma_channel); - // write-clear counter - writel(0x0, e_priv->write_transfer_counter); - - memcpy(e_priv->dma_buffer, buffer, length); - address = dma_map_single(board->dev, e_priv->dma_buffer, - length, DMA_TO_DEVICE); - /* program dma controller */ - retval = fluke_config_dma(board, 1); - if (retval) - goto cleanup; - - tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, address, length, DMA_MEM_TO_DEV, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!tx_desc) { - dev_err(board->gpib_dev, "failed to allocate dma transmit descriptor\n"); - retval = -ENOMEM; - goto cleanup; - } - tx_desc->callback = fluke_dma_callback; - tx_desc->callback_param = board; - - spin_lock_irqsave(&board->spinlock, flags); - nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0); - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO); - dmaengine_submit(tx_desc); - dma_async_issue_pending(e_priv->dma_channel); - - clear_bit(WRITE_READY_BN, &nec_priv->state); - set_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state); - - spin_unlock_irqrestore(&board->spinlock, flags); - - // suspend until message is sent - if (wait_event_interruptible(board->wait, - ((readl(e_priv->write_transfer_counter) & - write_transfer_counter_mask) == length) || - test_bit(BUS_ERROR_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - retval = -ERESTARTSYS; - } - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state)) - retval = -EIO; - // disable board's dma - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0); - - dmaengine_terminate_all(e_priv->dma_channel); - // make sure fluke_dma_callback got called - if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state)) - fluke_dma_callback(board); - - /* - * if everything went fine, try to wait until last byte is actually - * transmitted across gpib (but don't try _too_ hard) - */ - if (retval == 0) - retval = wait_for_sids_or_sgns(board); - - *bytes_written = readl(e_priv->write_transfer_counter) & write_transfer_counter_mask; - if (WARN_ON_ONCE(*bytes_written > length)) - return -EFAULT; - -cleanup: - dma_unmap_single(board->dev, address, length, DMA_TO_DEVICE); - return retval; -} - -static int fluke_accel_write(struct gpib_board *board, u8 *buffer, size_t length, - int send_eoi, size_t *bytes_written) -{ - struct fluke_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - size_t remainder = length; - size_t transfer_size; - ssize_t retval = 0; - size_t dma_remainder = remainder; - - if (!e_priv->dma_channel) { - dev_err(board->gpib_dev, "No dma channel available, cannot do accel write."); - return -ENXIO; - } - - *bytes_written = 0; - if (length < 1) - return 0; - - clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME - - if (send_eoi) - --dma_remainder; - - while (dma_remainder > 0) { - size_t num_bytes; - - retval = wait_for_data_out_ready(board); - if (retval < 0) - break; - - transfer_size = (e_priv->dma_buffer_size < dma_remainder) ? - e_priv->dma_buffer_size : dma_remainder; - retval = fluke_dma_write(board, buffer, transfer_size, &num_bytes); - *bytes_written += num_bytes; - if (retval < 0) - break; - dma_remainder -= num_bytes; - remainder -= num_bytes; - buffer += num_bytes; - if (need_resched()) - schedule(); - } - if (retval < 0) - return retval; - // handle sending of last byte with eoi - if (send_eoi) { - size_t num_bytes; - - if (WARN_ON_ONCE(remainder != 1)) - return -EFAULT; - - /* - * wait until we are sure we will be able to write the data byte - * into the chip before we send AUX_SEOI. This prevents a timeout - * scenerio where we send AUX_SEOI but then timeout without getting - * any bytes into the gpib chip. This will result in the first byte - * of the next write having a spurious EOI set on the first byte. - */ - retval = wait_for_data_out_ready(board); - if (retval < 0) - return retval; - - write_byte(nec_priv, AUX_SEOI, AUXMR); - retval = fluke_dma_write(board, buffer, remainder, &num_bytes); - *bytes_written += num_bytes; - if (retval < 0) - return retval; - remainder -= num_bytes; - } - return 0; -} - -static int fluke_get_dma_residue(struct dma_chan *chan, dma_cookie_t cookie) -{ - struct dma_tx_state state; - int result; - - result = dmaengine_pause(chan); - if (result < 0) { - pr_err("dma pause failed?\n"); - return result; - } - dmaengine_tx_status(chan, cookie, &state); - /* - * hardware doesn't support resume, so dont call this - * method unless the dma transfer is done. - */ - return state.residue; -} - -static int fluke_dma_read(struct gpib_board *board, u8 *buffer, - size_t length, int *end, size_t *bytes_read) -{ - struct fluke_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - int retval = 0; - unsigned long flags; - int residue; - dma_addr_t bus_address; - struct dma_async_tx_descriptor *tx_desc; - dma_cookie_t dma_cookie; - int i; - static const int timeout = 10; - - *bytes_read = 0; - *end = 0; - if (length == 0) - return 0; - - bus_address = dma_map_single(board->dev, e_priv->dma_buffer, - length, DMA_FROM_DEVICE); - - /* program dma controller */ - retval = fluke_config_dma(board, 0); - if (retval) { - dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE); - return retval; - } - tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, - bus_address, length, DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!tx_desc) { - dev_err(board->gpib_dev, "failed to allocate dma transmit descriptor\n"); - dma_unmap_single(NULL, bus_address, length, DMA_FROM_DEVICE); - return -EIO; - } - tx_desc->callback = fluke_dma_callback; - tx_desc->callback_param = board; - - spin_lock_irqsave(&board->spinlock, flags); - // enable nec7210 dma - nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, 0); - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI); - - dma_cookie = dmaengine_submit(tx_desc); - dma_async_issue_pending(e_priv->dma_channel); - - set_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state); - clear_bit(READ_READY_BN, &nec_priv->state); - - spin_unlock_irqrestore(&board->spinlock, flags); - // wait for data to transfer - if (wait_event_interruptible(board->wait, - test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state) == 0 || - test_bit(RECEIVED_END_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - retval = -ERESTARTSYS; - } - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - - /* - * If we woke up because of end, wait until the dma transfer has pulled - * the data byte associated with the end before we cancel the dma transfer. - */ - if (test_bit(RECEIVED_END_BN, &nec_priv->state)) { - for (i = 0; i < timeout; ++i) { - if (test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state) == 0) - break; - if ((read_byte(nec_priv, ADR0) & DATA_IN_STATUS) == 0) - break; - usleep_range(10, 15); - } - if (i == timeout) - pr_warn("fluke_gpib: timeout waiting for dma to transfer end data byte.\n"); - } - - // stop the dma transfer - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); - /* - * delay a little just to make sure any bytes in dma controller's fifo get - * written to memory before we disable it - */ - usleep_range(10, 15); - residue = fluke_get_dma_residue(e_priv->dma_channel, dma_cookie); - if (WARN_ON_ONCE(residue > length || residue < 0)) - return -EFAULT; - *bytes_read += length - residue; - dmaengine_terminate_all(e_priv->dma_channel); - // make sure fluke_dma_callback got called - if (test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state)) - fluke_dma_callback(board); - - dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE); - memcpy(buffer, e_priv->dma_buffer, *bytes_read); - - /* - * If we got an end interrupt, figure out if it was - * associated with the last byte we dma'd or with a - * byte still sitting on the cb7210. - */ - spin_lock_irqsave(&board->spinlock, flags); - if (test_bit(READ_READY_BN, &nec_priv->state) == 0) { - /* - * There is no byte sitting on the cb7210. If we - * saw an end interrupt, we need to deal with it now - */ - if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state)) - *end = 1; - } - spin_unlock_irqrestore(&board->spinlock, flags); - - return retval; -} - -static int fluke_accel_read(struct gpib_board *board, u8 *buffer, size_t length, - int *end, size_t *bytes_read) -{ - struct fluke_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - size_t remain = length; - size_t transfer_size; - int retval = 0; - size_t dma_nbytes; - - *end = 0; - *bytes_read = 0; - - smp_mb__before_atomic(); - clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME - smp_mb__after_atomic(); - - retval = wait_for_read(board); - if (retval < 0) - return retval; - - nec7210_release_rfd_holdoff(board, nec_priv); - - while (remain > 0) { - transfer_size = (e_priv->dma_buffer_size < remain) ? - e_priv->dma_buffer_size : remain; - retval = fluke_dma_read(board, buffer, transfer_size, end, &dma_nbytes); - remain -= dma_nbytes; - buffer += dma_nbytes; - *bytes_read += dma_nbytes; - if (*end) - break; - if (retval < 0) - return retval; - if (need_resched()) - schedule(); - } - - return retval; -} - -static struct gpib_interface fluke_unaccel_interface = { - .name = "fluke_unaccel", - .attach = fluke_attach_holdoff_all, - .detach = fluke_detach, - .read = fluke_read, - .write = fluke_write, - .command = fluke_command, - .take_control = fluke_take_control, - .go_to_standby = fluke_go_to_standby, - .request_system_control = fluke_request_system_control, - .interface_clear = fluke_interface_clear, - .remote_enable = fluke_remote_enable, - .enable_eos = fluke_enable_eos, - .disable_eos = fluke_disable_eos, - .parallel_poll = fluke_parallel_poll, - .parallel_poll_configure = fluke_parallel_poll_configure, - .parallel_poll_response = fluke_parallel_poll_response, - .line_status = fluke_line_status, - .update_status = fluke_update_status, - .primary_address = fluke_primary_address, - .secondary_address = fluke_secondary_address, - .serial_poll_response = fluke_serial_poll_response, - .serial_poll_status = fluke_serial_poll_status, - .t1_delay = fluke_t1_delay, - .return_to_local = fluke_return_to_local, -}; - -/* - * fluke_hybrid uses dma for writes but not for reads. Added - * to deal with occasional corruption of bytes seen when doing dma - * reads. From looking at the cb7210 vhdl, I believe the corruption - * is due to a hardware bug triggered by the cpu reading a cb7210 - * } - * register just as the dma controller is also doing a read. - */ - -static struct gpib_interface fluke_hybrid_interface = { - .name = "fluke_hybrid", - .attach = fluke_attach_holdoff_all, - .detach = fluke_detach, - .read = fluke_read, - .write = fluke_accel_write, - .command = fluke_command, - .take_control = fluke_take_control, - .go_to_standby = fluke_go_to_standby, - .request_system_control = fluke_request_system_control, - .interface_clear = fluke_interface_clear, - .remote_enable = fluke_remote_enable, - .enable_eos = fluke_enable_eos, - .disable_eos = fluke_disable_eos, - .parallel_poll = fluke_parallel_poll, - .parallel_poll_configure = fluke_parallel_poll_configure, - .parallel_poll_response = fluke_parallel_poll_response, - .line_status = fluke_line_status, - .update_status = fluke_update_status, - .primary_address = fluke_primary_address, - .secondary_address = fluke_secondary_address, - .serial_poll_response = fluke_serial_poll_response, - .serial_poll_status = fluke_serial_poll_status, - .t1_delay = fluke_t1_delay, - .return_to_local = fluke_return_to_local, -}; - -static struct gpib_interface fluke_interface = { - .name = "fluke", - .attach = fluke_attach_holdoff_end, - .detach = fluke_detach, - .read = fluke_accel_read, - .write = fluke_accel_write, - .command = fluke_command, - .take_control = fluke_take_control, - .go_to_standby = fluke_go_to_standby, - .request_system_control = fluke_request_system_control, - .interface_clear = fluke_interface_clear, - .remote_enable = fluke_remote_enable, - .enable_eos = fluke_enable_eos, - .disable_eos = fluke_disable_eos, - .parallel_poll = fluke_parallel_poll, - .parallel_poll_configure = fluke_parallel_poll_configure, - .parallel_poll_response = fluke_parallel_poll_response, - .line_status = fluke_line_status, - .update_status = fluke_update_status, - .primary_address = fluke_primary_address, - .secondary_address = fluke_secondary_address, - .serial_poll_response = fluke_serial_poll_response, - .serial_poll_status = fluke_serial_poll_status, - .t1_delay = fluke_t1_delay, - .return_to_local = fluke_return_to_local, -}; - -irqreturn_t fluke_gpib_internal_interrupt(struct gpib_board *board) -{ - int status0, status1, status2; - struct fluke_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - int retval = IRQ_NONE; - - if (read_byte(nec_priv, ADR0) & DATA_IN_STATUS) - set_bit(READ_READY_BN, &nec_priv->state); - - status0 = fluke_paged_read_byte(priv, ISR0_IMR0, ISR0_IMR0_PAGE); - status1 = read_byte(nec_priv, ISR1); - status2 = read_byte(nec_priv, ISR2); - - if (status0 & FLUKE_IFCI_BIT) { - push_gpib_event(board, EVENT_IFC); - retval = IRQ_HANDLED; - } - - if (nec7210_interrupt_have_status(board, nec_priv, status1, status2) == IRQ_HANDLED) - retval = IRQ_HANDLED; - - if (read_byte(nec_priv, ADR0) & DATA_IN_STATUS) { - if (test_bit(RFD_HOLDOFF_BN, &nec_priv->state)) - set_bit(READ_READY_BN, &nec_priv->state); - else - clear_bit(READ_READY_BN, &nec_priv->state); - } - - if (retval == IRQ_HANDLED) - wake_up_interruptible(&board->wait); - - return retval; -} - -static irqreturn_t fluke_gpib_interrupt(int irq, void *arg) -{ - struct gpib_board *board = arg; - unsigned long flags; - irqreturn_t retval; - - spin_lock_irqsave(&board->spinlock, flags); - retval = fluke_gpib_internal_interrupt(board); - spin_unlock_irqrestore(&board->spinlock, flags); - return retval; -} - -static int fluke_allocate_private(struct gpib_board *board) -{ - struct fluke_priv *priv; - - board->private_data = kmalloc(sizeof(struct fluke_priv), GFP_KERNEL); - if (!board->private_data) - return -ENOMEM; - priv = board->private_data; - memset(priv, 0, sizeof(struct fluke_priv)); - init_nec7210_private(&priv->nec7210_priv); - priv->dma_buffer_size = 0x7ff; - priv->dma_buffer = kmalloc(priv->dma_buffer_size, GFP_KERNEL); - if (!priv->dma_buffer) - return -ENOMEM; - return 0; -} - -static void fluke_generic_detach(struct gpib_board *board) -{ - if (board->private_data) { - struct fluke_priv *e_priv = board->private_data; - - kfree(e_priv->dma_buffer); - kfree(board->private_data); - board->private_data = NULL; - } -} - -// generic part of attach functions shared by all cb7210 boards -static int fluke_generic_attach(struct gpib_board *board) -{ - struct fluke_priv *e_priv; - struct nec7210_priv *nec_priv; - int retval; - - board->status = 0; - - retval = fluke_allocate_private(board); - if (retval < 0) - return retval; - e_priv = board->private_data; - nec_priv = &e_priv->nec7210_priv; - nec_priv->read_byte = fluke_locking_read_byte; - nec_priv->write_byte = fluke_locking_write_byte; - nec_priv->offset = fluke_reg_offset; - nec_priv->type = CB7210; - return 0; -} - -static int fluke_config_dma(struct gpib_board *board, int output) -{ - struct fluke_priv *e_priv = board->private_data; - struct dma_slave_config config; - - config.src_maxburst = 1; - config.dst_maxburst = 1; - config.device_fc = true; - - if (output) { - config.direction = DMA_MEM_TO_DEV; - config.src_addr = 0; - config.dst_addr = e_priv->dma_port_res->start; - config.src_addr_width = 1; - config.dst_addr_width = 1; - } else { - config.direction = DMA_DEV_TO_MEM; - config.src_addr = e_priv->dma_port_res->start; - config.dst_addr = 0; - config.src_addr_width = 1; - config.dst_addr_width = 1; - } - return dmaengine_slave_config(e_priv->dma_channel, &config); -} - -static int fluke_init(struct fluke_priv *e_priv, struct gpib_board *board, int handshake_mode) -{ - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - - nec7210_board_reset(nec_priv, board); - write_byte(nec_priv, AUX_LO_SPEED, AUXMR); - /* - * set clock register for driving frequency - * ICR should be set to clock in megahertz (1-15) and to zero - * for clocks faster than 15 MHz (max 20MHz) - */ - write_byte(nec_priv, ICR | 10, AUXMR); - nec7210_set_handshake_mode(board, nec_priv, handshake_mode); - - nec7210_board_online(nec_priv, board); - - /* poll so we can detect ATN changes */ - if (gpib_request_pseudo_irq(board, fluke_gpib_interrupt)) { - dev_err(board->gpib_dev, "failed to allocate pseudo_irq\n"); - return -EINVAL; - } - - fluke_paged_write_byte(e_priv, FLUKE_IFCIE_BIT, ISR0_IMR0, ISR0_IMR0_PAGE); - return 0; -} - -/* - * This function is passed to dma_request_channel() in order to - * select the pl330 dma channel which has been hardwired to - * the gpib controller. - */ -static bool gpib_dma_channel_filter(struct dma_chan *chan, void *filter_param) -{ - // select the channel which is wired to the gpib chip - return chan->chan_id == 0; -} - -static int fluke_attach_impl(struct gpib_board *board, const struct gpib_board_config *config, - unsigned int handshake_mode) -{ - struct fluke_priv *e_priv; - struct nec7210_priv *nec_priv; - int isr_flags = 0; - int retval; - int irq; - struct resource *res; - dma_cap_mask_t dma_cap; - - if (!fluke_gpib_pdev) { - dev_err(board->gpib_dev, "No fluke device was found, attach failed.\n"); - return -ENODEV; - } - - retval = fluke_generic_attach(board); - if (retval) - return retval; - - e_priv = board->private_data; - nec_priv = &e_priv->nec7210_priv; - nec_priv->offset = fluke_reg_offset; - board->dev = &fluke_gpib_pdev->dev; - - res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource\n"); - return -ENODEV; - } - - if (request_mem_region(res->start, - resource_size(res), - fluke_gpib_pdev->name) == NULL) { - dev_err(&fluke_gpib_pdev->dev, "cannot claim registers\n"); - return -ENXIO; - } - e_priv->gpib_iomem_res = res; - - nec_priv->mmiobase = ioremap(e_priv->gpib_iomem_res->start, - resource_size(e_priv->gpib_iomem_res)); - if (!nec_priv->mmiobase) { - dev_err(&fluke_gpib_pdev->dev, "Could not map I/O memory\n"); - return -ENOMEM; - } - - res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 1); - if (!res) { - dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource for gpib dma port\n"); - return -ENODEV; - } - if (request_mem_region(res->start, - resource_size(res), - fluke_gpib_pdev->name) == NULL) { - dev_err(&fluke_gpib_pdev->dev, "cannot claim registers\n"); - return -ENXIO; - } - e_priv->dma_port_res = res; - - res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 2); - if (!res) { - dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource for write transfer counter\n"); - return -ENODEV; - } - - if (request_mem_region(res->start, - resource_size(res), - fluke_gpib_pdev->name) == NULL) { - dev_err(&fluke_gpib_pdev->dev, "cannot claim registers\n"); - return -ENXIO; - } - e_priv->write_transfer_counter_res = res; - - e_priv->write_transfer_counter = ioremap(e_priv->write_transfer_counter_res->start, - resource_size(e_priv->write_transfer_counter_res)); - if (!e_priv->write_transfer_counter) { - dev_err(&fluke_gpib_pdev->dev, "Could not map I/O memory\n"); - return -ENOMEM; - } - - irq = platform_get_irq(fluke_gpib_pdev, 0); - if (irq < 0) - return -EBUSY; - retval = request_irq(irq, fluke_gpib_interrupt, isr_flags, fluke_gpib_pdev->name, board); - if (retval) { - dev_err(&fluke_gpib_pdev->dev, - "cannot register interrupt handler err=%d\n", - retval); - return retval; - } - e_priv->irq = irq; - - dma_cap_zero(dma_cap); - dma_cap_set(DMA_SLAVE, dma_cap); - e_priv->dma_channel = dma_request_channel(dma_cap, gpib_dma_channel_filter, NULL); - if (!e_priv->dma_channel) { - dev_err(board->gpib_dev, "failed to allocate a dma channel.\n"); - /* - * we don't error out here because unaccel interface will still - * work without dma - */ - } - - return fluke_init(e_priv, board, handshake_mode); -} - -int fluke_attach_holdoff_all(struct gpib_board *board, const struct gpib_board_config *config) -{ - return fluke_attach_impl(board, config, HR_HLDA); -} - -int fluke_attach_holdoff_end(struct gpib_board *board, const struct gpib_board_config *config) -{ - return fluke_attach_impl(board, config, HR_HLDE); -} - -void fluke_detach(struct gpib_board *board) -{ - struct fluke_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (e_priv) { - if (e_priv->dma_channel) - dma_release_channel(e_priv->dma_channel); - gpib_free_pseudo_irq(board); - nec_priv = &e_priv->nec7210_priv; - - if (nec_priv->mmiobase) { - fluke_paged_write_byte(e_priv, 0, ISR0_IMR0, ISR0_IMR0_PAGE); - nec7210_board_reset(nec_priv, board); - } - if (e_priv->irq) - free_irq(e_priv->irq, board); - if (e_priv->write_transfer_counter_res) { - release_mem_region(e_priv->write_transfer_counter_res->start, - resource_size(e_priv->write_transfer_counter_res)); - } - if (e_priv->dma_port_res) { - release_mem_region(e_priv->dma_port_res->start, - resource_size(e_priv->dma_port_res)); - } - if (e_priv->gpib_iomem_res) - release_mem_region(e_priv->gpib_iomem_res->start, - resource_size(e_priv->gpib_iomem_res)); - } - fluke_generic_detach(board); -} - -static int fluke_gpib_probe(struct platform_device *pdev) -{ - fluke_gpib_pdev = pdev; - return 0; -} - -static const struct of_device_id fluke_gpib_of_match[] = { - { .compatible = "flk,fgpib-4.0"}, - { {0} } -}; -MODULE_DEVICE_TABLE(of, fluke_gpib_of_match); - -static struct platform_driver fluke_gpib_platform_driver = { - .driver = { - .name = DRV_NAME, - .of_match_table = fluke_gpib_of_match, - }, - .probe = &fluke_gpib_probe -}; - -static int __init fluke_init_module(void) -{ - int result; - - result = platform_driver_register(&fluke_gpib_platform_driver); - if (result) { - pr_err("platform_driver_register failed: error = %d\n", result); - return result; - } - - result = gpib_register_driver(&fluke_unaccel_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_unaccel; - } - - result = gpib_register_driver(&fluke_hybrid_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_hybrid; - } - - result = gpib_register_driver(&fluke_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_interface; - } - - return 0; - -err_interface: - gpib_unregister_driver(&fluke_hybrid_interface); -err_hybrid: - gpib_unregister_driver(&fluke_unaccel_interface); -err_unaccel: - platform_driver_unregister(&fluke_gpib_platform_driver); - - return result; -} - -static void __exit fluke_exit_module(void) -{ - gpib_unregister_driver(&fluke_unaccel_interface); - gpib_unregister_driver(&fluke_hybrid_interface); - gpib_unregister_driver(&fluke_interface); - platform_driver_unregister(&fluke_gpib_platform_driver); -} - -module_init(fluke_init_module); -module_exit(fluke_exit_module); diff --git a/drivers/staging/gpib/eastwood/fluke_gpib.h b/drivers/staging/gpib/eastwood/fluke_gpib.h deleted file mode 100644 index 493c200d0bbf..000000000000 --- a/drivers/staging/gpib/eastwood/fluke_gpib.h +++ /dev/null @@ -1,146 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * Author: Frank Mori Hess <fmh6jj@gmail.com> - * copyright: (C) 2006, 2010, 2015 Fluke Corporation - ***************************************************************************/ - -#include <linux/compiler.h> -#include <linux/dmaengine.h> -#include <linux/io.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include "nec7210.h" - -struct fluke_priv { - struct nec7210_priv nec7210_priv; - struct resource *gpib_iomem_res; - struct resource *write_transfer_counter_res; - struct resource *dma_port_res; - int irq; - struct dma_chan *dma_channel; - u8 *dma_buffer; - int dma_buffer_size; - void __iomem *write_transfer_counter; -}; - -// cb7210 specific registers and bits -enum cb7210_regs { - STATE1_REG = 0x4, - ISR0_IMR0 = 0x6, - BUS_STATUS = 0x7 -}; - -enum cb7210_page_in { - ISR0_IMR0_PAGE = 1, - BUS_STATUS_PAGE = 1, - STATE1_PAGE = 1 -}; - -/* IMR0 -- Interrupt Mode Register 0 */ -enum imr0_bits { - FLUKE_IFCIE_BIT = 0x8, /* interface clear interrupt */ -}; - -/* ISR0 -- Interrupt Status Register 0 */ -enum isr0_bits { - FLUKE_IFCI_BIT = 0x8, /* interface clear interrupt */ -}; - -enum state1_bits { - SOURCE_HANDSHAKE_SIDS_BITS = 0x0, /* source idle state */ - SOURCE_HANDSHAKE_SGNS_BITS = 0x1, /* source generate state */ - SOURCE_HANDSHAKE_SDYS_BITS = 0x2, /* source delay state */ - SOURCE_HANDSHAKE_STRS_BITS = 0x5, /* source transfer state */ - SOURCE_HANDSHAKE_MASK = 0x7 -}; - -/* - * we customized the cb7210 vhdl to give the "data in" status - * on the unused bit 7 of the address0 register. - */ -enum cb7210_address0 { - DATA_IN_STATUS = 0x80 -}; - -static inline int cb7210_page_in_bits(unsigned int page) -{ - return 0x50 | (page & 0xf); -} - -// don't use without locking nec_priv->register_page_lock -static inline u8 fluke_read_byte_nolock(struct nec7210_priv *nec_priv, - int register_num) -{ - u8 retval; - - retval = readl(nec_priv->mmiobase + register_num * nec_priv->offset); - return retval; -} - -// don't use without locking nec_priv->register_page_lock -static inline void fluke_write_byte_nolock(struct nec7210_priv *nec_priv, u8 data, - int register_num) -{ - writel(data, nec_priv->mmiobase + register_num * nec_priv->offset); -} - -static inline u8 fluke_paged_read_byte(struct fluke_priv *e_priv, - unsigned int register_num, unsigned int page) -{ - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - u8 retval; - unsigned long flags; - - spin_lock_irqsave(&nec_priv->register_page_lock, flags); - fluke_write_byte_nolock(nec_priv, cb7210_page_in_bits(page), AUXMR); - udelay(1); - /* chip auto clears the page after a read */ - retval = fluke_read_byte_nolock(nec_priv, register_num); - spin_unlock_irqrestore(&nec_priv->register_page_lock, flags); - return retval; -} - -static inline void fluke_paged_write_byte(struct fluke_priv *e_priv, u8 data, - unsigned int register_num, unsigned int page) -{ - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - unsigned long flags; - - spin_lock_irqsave(&nec_priv->register_page_lock, flags); - fluke_write_byte_nolock(nec_priv, cb7210_page_in_bits(page), AUXMR); - udelay(1); - fluke_write_byte_nolock(nec_priv, data, register_num); - spin_unlock_irqrestore(&nec_priv->register_page_lock, flags); -} - -enum bus_status_bits { - BSR_ATN_BIT = 0x1, - BSR_EOI_BIT = 0x2, - BSR_SRQ_BIT = 0x4, - BSR_IFC_BIT = 0x8, - BSR_REN_BIT = 0x10, - BSR_DAV_BIT = 0x20, - BSR_NRFD_BIT = 0x40, - BSR_NDAC_BIT = 0x80, -}; - -enum cb7210_aux_cmds { -/* - * AUX_RTL2 is an undocumented aux command which causes cb7210 to assert - * (and keep asserted) local rtl message. This is used in conjunction - * with the (stupid) cb7210 implementation - * of the normal nec7210 AUX_RTL aux command, which - * causes the rtl message to toggle between on and off. - */ - AUX_RTL2 = 0xd, - AUX_NBAF = 0xe, // new byte available false (also clears seoi) - AUX_LO_SPEED = 0x40, - AUX_HI_SPEED = 0x41, -}; - -enum { - fluke_reg_offset = 4, - fluke_num_regs = 8, - write_transfer_counter_mask = 0x7ff, -}; diff --git a/drivers/staging/gpib/fmh_gpib/Makefile b/drivers/staging/gpib/fmh_gpib/Makefile deleted file mode 100644 index cc4d9e7cd5cd..000000000000 --- a/drivers/staging/gpib/fmh_gpib/Makefile +++ /dev/null @@ -1,2 +0,0 @@ - -obj-$(CONFIG_GPIB_FMH) += fmh_gpib.o diff --git a/drivers/staging/gpib/fmh_gpib/fmh_gpib.c b/drivers/staging/gpib/fmh_gpib/fmh_gpib.c deleted file mode 100644 index f7bfb4a8e553..000000000000 --- a/drivers/staging/gpib/fmh_gpib/fmh_gpib.c +++ /dev/null @@ -1,1754 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * GPIB Driver for fmh_gpib_core, see - * https://github.com/fmhess/fmh_gpib_core - * - * More specifically, it is a driver for the hardware arrangement described by - * src/examples/fmh_gpib_top.vhd in the fmh_gpib_core repository. - * - * Author: Frank Mori Hess <fmh6jj@gmail.com> - * Copyright: (C) 2006, 2010, 2015 Fluke Corporation - * (C) 2017 Frank Mori Hess - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define DRV_NAME KBUILD_MODNAME - -#include "fmh_gpib.h" - -#include "gpibP.h" -#include <linux/delay.h> -#include <linux/device.h> -#include <linux/dma-mapping.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/platform_device.h> -#include <linux/slab.h> - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB Driver for fmh_gpib_core"); -MODULE_AUTHOR("Frank Mori Hess <fmh6jj@gmail.com>"); - -static irqreturn_t fmh_gpib_interrupt(int irq, void *arg); -static int fmh_gpib_attach_holdoff_all(struct gpib_board *board, - const struct gpib_board_config *config); -static int fmh_gpib_attach_holdoff_end(struct gpib_board *board, - const struct gpib_board_config *config); -static void fmh_gpib_detach(struct gpib_board *board); -static int fmh_gpib_pci_attach_holdoff_all(struct gpib_board *board, - const struct gpib_board_config *config); -static int fmh_gpib_pci_attach_holdoff_end(struct gpib_board *board, - const struct gpib_board_config *config); -static void fmh_gpib_pci_detach(struct gpib_board *board); -static int fmh_gpib_config_dma(struct gpib_board *board, int output); -static irqreturn_t fmh_gpib_internal_interrupt(struct gpib_board *board); -static struct platform_driver fmh_gpib_platform_driver; -static struct pci_driver fmh_gpib_pci_driver; - -// wrappers for interface functions -static int fmh_gpib_read(struct gpib_board *board, u8 *buffer, size_t length, - int *end, size_t *bytes_read) -{ - struct fmh_priv *priv = board->private_data; - - return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); -} - -static int fmh_gpib_write(struct gpib_board *board, u8 *buffer, size_t length, - int send_eoi, size_t *bytes_written) -{ - struct fmh_priv *priv = board->private_data; - - return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); -} - -static int fmh_gpib_command(struct gpib_board *board, u8 *buffer, size_t length, - size_t *bytes_written) -{ - struct fmh_priv *priv = board->private_data; - - return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); -} - -static int fmh_gpib_take_control(struct gpib_board *board, int synchronous) -{ - struct fmh_priv *priv = board->private_data; - - return nec7210_take_control(board, &priv->nec7210_priv, synchronous); -} - -static int fmh_gpib_go_to_standby(struct gpib_board *board) -{ - struct fmh_priv *priv = board->private_data; - - return nec7210_go_to_standby(board, &priv->nec7210_priv); -} - -static int fmh_gpib_request_system_control(struct gpib_board *board, int request_control) -{ - struct fmh_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - - return nec7210_request_system_control(board, nec_priv, request_control); -} - -static void fmh_gpib_interface_clear(struct gpib_board *board, int assert) -{ - struct fmh_priv *priv = board->private_data; - - nec7210_interface_clear(board, &priv->nec7210_priv, assert); -} - -static void fmh_gpib_remote_enable(struct gpib_board *board, int enable) -{ - struct fmh_priv *priv = board->private_data; - - nec7210_remote_enable(board, &priv->nec7210_priv, enable); -} - -static int fmh_gpib_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits) -{ - struct fmh_priv *priv = board->private_data; - - return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); -} - -static void fmh_gpib_disable_eos(struct gpib_board *board) -{ - struct fmh_priv *priv = board->private_data; - - nec7210_disable_eos(board, &priv->nec7210_priv); -} - -static unsigned int fmh_gpib_update_status(struct gpib_board *board, unsigned int clear_mask) -{ - struct fmh_priv *priv = board->private_data; - - return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); -} - -static int fmh_gpib_primary_address(struct gpib_board *board, unsigned int address) -{ - struct fmh_priv *priv = board->private_data; - - return nec7210_primary_address(board, &priv->nec7210_priv, address); -} - -static int fmh_gpib_secondary_address(struct gpib_board *board, unsigned int address, int enable) -{ - struct fmh_priv *priv = board->private_data; - - return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); -} - -static int fmh_gpib_parallel_poll(struct gpib_board *board, u8 *result) -{ - struct fmh_priv *priv = board->private_data; - - return nec7210_parallel_poll(board, &priv->nec7210_priv, result); -} - -static void fmh_gpib_parallel_poll_configure(struct gpib_board *board, u8 configuration) -{ - struct fmh_priv *priv = board->private_data; - - nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration); -} - -static void fmh_gpib_parallel_poll_response(struct gpib_board *board, int ist) -{ - struct fmh_priv *priv = board->private_data; - - nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); -} - -static void fmh_gpib_local_parallel_poll_mode(struct gpib_board *board, int local) -{ - struct fmh_priv *priv = board->private_data; - - if (local) { - write_byte(&priv->nec7210_priv, AUX_I_REG | LOCAL_PPOLL_MODE_BIT, AUXMR); - } else { - /* - * For fmh_gpib_core, remote parallel poll config mode is unaffected by the - * state of the disable bit of the parallel poll register (unlike the tnt4882). - * So, we don't need to worry about that. - */ - write_byte(&priv->nec7210_priv, AUX_I_REG | 0x0, AUXMR); - } -} - -static void fmh_gpib_serial_poll_response2(struct gpib_board *board, u8 status, - int new_reason_for_service) -{ - struct fmh_priv *priv = board->private_data; - unsigned long flags; - const int MSS = status & request_service_bit; - const int reqt = MSS && new_reason_for_service; - const int reqf = MSS == 0; - - spin_lock_irqsave(&board->spinlock, flags); - if (reqt) { - priv->nec7210_priv.srq_pending = 1; - clear_bit(SPOLL_NUM, &board->status); - } else if (reqf) { - priv->nec7210_priv.srq_pending = 0; - } - - if (reqt) { - /* - * It may seem like a race to issue reqt before updating - * the status byte, but it is not. The chip does not - * issue the reqt until the SPMR is written to at - * a later time. - */ - write_byte(&priv->nec7210_priv, AUX_REQT, AUXMR); - } else if (reqf) { - write_byte(&priv->nec7210_priv, AUX_REQF, AUXMR); - } - /* - * We need to always zero bit 6 of the status byte before writing it to - * the SPMR to insure we are using - * serial poll mode SP1, and not accidentally triggering mode SP3. - */ - write_byte(&priv->nec7210_priv, status & ~request_service_bit, SPMR); - spin_unlock_irqrestore(&board->spinlock, flags); -} - -static u8 fmh_gpib_serial_poll_status(struct gpib_board *board) -{ - struct fmh_priv *priv = board->private_data; - - return nec7210_serial_poll_status(board, &priv->nec7210_priv); -} - -static void fmh_gpib_return_to_local(struct gpib_board *board) -{ - struct fmh_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - - write_byte(nec_priv, AUX_RTL2, AUXMR); - udelay(1); - write_byte(nec_priv, AUX_RTL, AUXMR); -} - -static int fmh_gpib_line_status(const struct gpib_board *board) -{ - int status = VALID_ALL; - int bsr_bits; - struct fmh_priv *e_priv; - struct nec7210_priv *nec_priv; - - e_priv = board->private_data; - nec_priv = &e_priv->nec7210_priv; - - bsr_bits = read_byte(nec_priv, BUS_STATUS_REG); - - if ((bsr_bits & BSR_REN_BIT) == 0) - status |= BUS_REN; - if ((bsr_bits & BSR_IFC_BIT) == 0) - status |= BUS_IFC; - if ((bsr_bits & BSR_SRQ_BIT) == 0) - status |= BUS_SRQ; - if ((bsr_bits & BSR_EOI_BIT) == 0) - status |= BUS_EOI; - if ((bsr_bits & BSR_NRFD_BIT) == 0) - status |= BUS_NRFD; - if ((bsr_bits & BSR_NDAC_BIT) == 0) - status |= BUS_NDAC; - if ((bsr_bits & BSR_DAV_BIT) == 0) - status |= BUS_DAV; - if ((bsr_bits & BSR_ATN_BIT) == 0) - status |= BUS_ATN; - - return status; -} - -static int fmh_gpib_t1_delay(struct gpib_board *board, unsigned int nano_sec) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - unsigned int retval; - - retval = nec7210_t1_delay(board, nec_priv, nano_sec); - - if (nano_sec <= 350) { - write_byte(nec_priv, AUX_HI_SPEED, AUXMR); - retval = 350; - } else { - write_byte(nec_priv, AUX_LO_SPEED, AUXMR); - } - return retval; -} - -static int lacs_or_read_ready(struct gpib_board *board) -{ - const struct fmh_priv *e_priv = board->private_data; - const struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - int retval = 0; - unsigned long flags; - - spin_lock_irqsave(&board->spinlock, flags); - retval = test_bit(LACS_NUM, &board->status) || - test_bit(READ_READY_BN, &nec_priv->state); - spin_unlock_irqrestore(&board->spinlock, flags); - - return retval; -} - -static int wait_for_read(struct gpib_board *board) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - int retval = 0; - - if (wait_event_interruptible(board->wait, - lacs_or_read_ready(board) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - return retval; -} - -static int wait_for_rx_fifo_half_full_or_end(struct gpib_board *board) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - int retval = 0; - - if (wait_event_interruptible(board->wait, - (fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) & - RX_FIFO_HALF_FULL) || - test_bit(RECEIVED_END_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - return retval; -} - -/* - * Wait until the gpib chip is ready to accept a data out byte. - */ -static int wait_for_data_out_ready(struct gpib_board *board) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - int retval = 0; - - if (wait_event_interruptible(board->wait, - (test_bit(TACS_NUM, &board->status) && - (read_byte(nec_priv, EXT_STATUS_1_REG) & - DATA_OUT_STATUS_BIT)) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - - return retval; -} - -static void fmh_gpib_dma_callback(void *arg) -{ - struct gpib_board *board = arg; - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - unsigned long flags; - - spin_lock_irqsave(&board->spinlock, flags); - - nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, HR_DOIE | HR_DIIE); - wake_up_interruptible(&board->wait); - - fmh_gpib_internal_interrupt(board); - - clear_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state); - clear_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state); - - spin_unlock_irqrestore(&board->spinlock, flags); -} - -/* - * returns true when all the bytes of a write have been transferred to - * the chip and successfully transferred out over the gpib bus. - */ -static int fmh_gpib_all_bytes_are_sent(struct fmh_priv *e_priv) -{ - if (fifos_read(e_priv, FIFO_XFER_COUNTER_REG) & fifo_xfer_counter_mask) - return 0; - - if ((read_byte(&e_priv->nec7210_priv, EXT_STATUS_1_REG) & DATA_OUT_STATUS_BIT) == 0) - return 0; - - return 1; -} - -static int fmh_gpib_dma_write(struct gpib_board *board, u8 *buffer, size_t length, - size_t *bytes_written) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - unsigned long flags; - int retval = 0; - dma_addr_t address; - struct dma_async_tx_descriptor *tx_desc; - - *bytes_written = 0; - if (WARN_ON_ONCE(length > e_priv->dma_buffer_size)) - return -EFAULT; - dmaengine_terminate_all(e_priv->dma_channel); - memcpy(e_priv->dma_buffer, buffer, length); - address = dma_map_single(board->dev, e_priv->dma_buffer, length, DMA_TO_DEVICE); - if (dma_mapping_error(board->dev, address)) - dev_err(board->gpib_dev, "dma mapping error in dma write!\n"); - /* program dma controller */ - retval = fmh_gpib_config_dma(board, 1); - if (retval) - goto cleanup; - - tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, address, length, DMA_MEM_TO_DEV, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!tx_desc) { - dev_err(board->gpib_dev, "failed to allocate dma transmit descriptor\n"); - retval = -ENOMEM; - goto cleanup; - } - tx_desc->callback = fmh_gpib_dma_callback; - tx_desc->callback_param = board; - - spin_lock_irqsave(&board->spinlock, flags); - fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG); - fifos_write(e_priv, TX_FIFO_DMA_REQUEST_ENABLE | TX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG); - nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0); - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO); - - dmaengine_submit(tx_desc); - dma_async_issue_pending(e_priv->dma_channel); - clear_bit(WRITE_READY_BN, &nec_priv->state); - set_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state); - - spin_unlock_irqrestore(&board->spinlock, flags); - - // suspend until message is sent - if (wait_event_interruptible(board->wait, - fmh_gpib_all_bytes_are_sent(e_priv) || - test_bit(BUS_ERROR_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state)) - retval = -EIO; - // disable board's dma - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0); - fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG); - - dmaengine_terminate_all(e_priv->dma_channel); - // make sure fmh_gpib_dma_callback got called - if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state)) - fmh_gpib_dma_callback(board); - - *bytes_written = length - (fifos_read(e_priv, FIFO_XFER_COUNTER_REG) & - fifo_xfer_counter_mask); - if (WARN_ON_ONCE(*bytes_written > length)) - return -EFAULT; -cleanup: - dma_unmap_single(board->dev, address, length, DMA_TO_DEVICE); - return retval; -} - -static int fmh_gpib_accel_write(struct gpib_board *board, u8 *buffer, - size_t length, int send_eoi, size_t *bytes_written) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - size_t remainder = length; - size_t transfer_size; - ssize_t retval = 0; - size_t dma_remainder = remainder; - - if (!e_priv->dma_channel) { - dev_err(board->gpib_dev, "No dma channel available, cannot do accel write."); - return -ENXIO; - } - - *bytes_written = 0; - if (length < 1) - return 0; - - smp_mb__before_atomic(); - clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME - smp_mb__after_atomic(); - - if (send_eoi) - --dma_remainder; - - while (dma_remainder > 0) { - size_t num_bytes; - - retval = wait_for_data_out_ready(board); - if (retval < 0) - break; - - transfer_size = (e_priv->dma_buffer_size < dma_remainder) ? - e_priv->dma_buffer_size : dma_remainder; - retval = fmh_gpib_dma_write(board, buffer, transfer_size, &num_bytes); - *bytes_written += num_bytes; - if (retval < 0) - break; - dma_remainder -= num_bytes; - remainder -= num_bytes; - buffer += num_bytes; - if (need_resched()) - schedule(); - } - if (retval < 0) - return retval; - // handle sending of last byte with eoi - if (send_eoi) { - size_t num_bytes; - - if (WARN_ON_ONCE(remainder != 1)) - return -EFAULT; - - /* - * wait until we are sure we will be able to write the data byte - * into the chip before we send AUX_SEOI. This prevents a timeout - * scenario where we send AUX_SEOI but then timeout without getting - * any bytes into the gpib chip. This will result in the first byte - * of the next write having a spurious EOI set on the first byte. - */ - retval = wait_for_data_out_ready(board); - if (retval < 0) - return retval; - - write_byte(nec_priv, AUX_SEOI, AUXMR); - retval = fmh_gpib_dma_write(board, buffer, remainder, &num_bytes); - *bytes_written += num_bytes; - if (retval < 0) - return retval; - remainder -= num_bytes; - } - return 0; -} - -static int fmh_gpib_get_dma_residue(struct dma_chan *chan, dma_cookie_t cookie) -{ - struct dma_tx_state state; - int result; - - result = dmaengine_pause(chan); - if (result < 0) { - pr_err("dma pause failed?\n"); - return result; - } - dmaengine_tx_status(chan, cookie, &state); - /* - * dma330 hardware doesn't support resume, so dont call this - * method unless the dma transfer is done. - */ - return state.residue; -} - -static int wait_for_tx_fifo_half_empty(struct gpib_board *board) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - int retval = 0; - - if (wait_event_interruptible(board->wait, - (test_bit(TACS_NUM, &board->status) && - (fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) & - TX_FIFO_HALF_EMPTY)) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - - return retval; -} - -/* - * supports writing a chunk of data whose length must fit into the hardware'd xfer counter, - * called in a loop by fmh_gpib_fifo_write() - */ -static int fmh_gpib_fifo_write_countable(struct gpib_board *board, u8 *buffer, - size_t length, int send_eoi, size_t *bytes_written) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - int retval = 0; - unsigned int remainder; - - *bytes_written = 0; - if (WARN_ON_ONCE(length > fifo_xfer_counter_mask)) - return -EFAULT; - - fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG); - fifos_write(e_priv, TX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG); - nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0); - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO); - - remainder = length; - while (remainder > 0) { - int i; - - fifos_write(e_priv, TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE, FIFO_CONTROL_STATUS_REG); - retval = wait_for_tx_fifo_half_empty(board); - if (retval < 0) - goto cleanup; - - for (i = 0; i < fmh_gpib_half_fifo_size(e_priv) && remainder > 0; ++i) { - unsigned int data_value = *buffer; - - if (send_eoi && remainder == 1) - data_value |= FIFO_DATA_EOI_FLAG; - fifos_write(e_priv, data_value, FIFO_DATA_REG); - ++buffer; - --remainder; - } - } - - // suspend until last byte is sent - nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, HR_DOIE); - if (wait_event_interruptible(board->wait, - fmh_gpib_all_bytes_are_sent(e_priv) || - test_bit(BUS_ERROR_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state)) - retval = -EIO; - -cleanup: - nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0); - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0); - fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG); - - *bytes_written = length - (fifos_read(e_priv, FIFO_XFER_COUNTER_REG) & - fifo_xfer_counter_mask); - if (WARN_ON_ONCE(*bytes_written > length)) - return -EFAULT; - - return retval; -} - -static int fmh_gpib_fifo_write(struct gpib_board *board, u8 *buffer, size_t length, - int send_eoi, size_t *bytes_written) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - size_t remainder = length; - size_t transfer_size; - ssize_t retval = 0; - - *bytes_written = 0; - if (length < 1) - return 0; - - clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME - - while (remainder > 0) { - size_t num_bytes; - int last_pass; - - retval = wait_for_data_out_ready(board); - if (retval < 0) - break; - - if (fifo_xfer_counter_mask < remainder) { - // round transfer size to a multiple of half fifo size - transfer_size = (fifo_xfer_counter_mask / - fmh_gpib_half_fifo_size(e_priv)) * - fmh_gpib_half_fifo_size(e_priv); - last_pass = 0; - } else { - transfer_size = remainder; - last_pass = 1; - } - retval = fmh_gpib_fifo_write_countable(board, buffer, transfer_size, - last_pass && send_eoi, &num_bytes); - *bytes_written += num_bytes; - if (retval < 0) - break; - remainder -= num_bytes; - buffer += num_bytes; - if (need_resched()) - schedule(); - } - - return retval; -} - -static int fmh_gpib_dma_read(struct gpib_board *board, u8 *buffer, - size_t length, int *end, size_t *bytes_read) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - int retval = 0; - unsigned long flags; - int residue; - int wait_retval; - dma_addr_t bus_address; - struct dma_async_tx_descriptor *tx_desc; - dma_cookie_t dma_cookie; - - *bytes_read = 0; - *end = 0; - if (length == 0) - return 0; - - bus_address = dma_map_single(board->dev, e_priv->dma_buffer, - length, DMA_FROM_DEVICE); - if (dma_mapping_error(board->dev, bus_address)) - dev_err(board->gpib_dev, "dma mapping error in dma read!"); - - /* program dma controller */ - retval = fmh_gpib_config_dma(board, 0); - if (retval) { - dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE); - return retval; - } - tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, bus_address, - length, DMA_DEV_TO_MEM, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!tx_desc) { - dev_err(board->gpib_dev, "failed to allocate dma transmit descriptor\n"); - dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE); - return -EIO; - } - tx_desc->callback = fmh_gpib_dma_callback; - tx_desc->callback_param = board; - - spin_lock_irqsave(&board->spinlock, flags); - // enable nec7210 dma - fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG); - fifos_write(e_priv, RX_FIFO_DMA_REQUEST_ENABLE | RX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG); - nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, 0); - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI); - - dma_cookie = dmaengine_submit(tx_desc); - dma_async_issue_pending(e_priv->dma_channel); - - set_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state); - - spin_unlock_irqrestore(&board->spinlock, flags); - - // wait for data to transfer - wait_retval = wait_event_interruptible(board->wait, - test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state) - == 0 || - test_bit(RECEIVED_END_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status)); - if (wait_retval) - retval = -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - // stop the dma transfer - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); - fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG); - /* - * give time for pl330 to transfer any in-flight data, since - * pl330 will throw it away when dmaengine_pause is called. - */ - usleep_range(10, 15); - residue = fmh_gpib_get_dma_residue(e_priv->dma_channel, dma_cookie); - if (WARN_ON_ONCE(residue > length || residue < 0)) - return -EFAULT; - *bytes_read += length - residue; - dmaengine_terminate_all(e_priv->dma_channel); - // make sure fmh_gpib_dma_callback got called - if (test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state)) - fmh_gpib_dma_callback(board); - - dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE); - memcpy(buffer, e_priv->dma_buffer, *bytes_read); - - /* Manually read any dregs out of fifo. */ - while ((fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) & RX_FIFO_EMPTY) == 0) { - if ((*bytes_read) >= length) { - dev_err(board->dev, "unexpected extra bytes in rx fifo, discarding! bytes_read=%d length=%d residue=%d\n", - (int)(*bytes_read), (int)length, (int)residue); - break; - } - buffer[(*bytes_read)++] = fifos_read(e_priv, FIFO_DATA_REG) & fifo_data_mask; - } - - /* - * If we got an end interrupt, figure out if it was - * associated with the last byte we dma'd or with a - * byte still sitting on the cb7210. - */ - spin_lock_irqsave(&board->spinlock, flags); - if (*bytes_read > 0 && test_bit(READ_READY_BN, &nec_priv->state) == 0) { - /* - * If there is no byte sitting on the cb7210 and we - * saw an end, we need to deal with it now - */ - if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state)) - *end = 1; - } - spin_unlock_irqrestore(&board->spinlock, flags); - - return retval; -} - -static void fmh_gpib_release_rfd_holdoff(struct gpib_board *board, struct fmh_priv *e_priv) -{ - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - unsigned int ext_status_1; - unsigned long flags; - - spin_lock_irqsave(&board->spinlock, flags); - - ext_status_1 = read_byte(nec_priv, EXT_STATUS_1_REG); - - /* - * if there is an end byte sitting on the chip, don't release - * holdoff. We want it left set after we read out the end - * byte. - */ - if ((ext_status_1 & (DATA_IN_STATUS_BIT | END_STATUS_BIT)) != - (DATA_IN_STATUS_BIT | END_STATUS_BIT)) { - if (ext_status_1 & RFD_HOLDOFF_STATUS_BIT) - write_byte(nec_priv, AUX_FH, AUXMR); - - /* - * Check if an end byte raced in before we executed the AUX_FH command. - * If it did, we want to make sure the rfd holdoff is in effect. The end - * byte can arrive since - * AUX_RFD_HOLDOFF_ASAP doesn't immediately force the acceptor handshake - * to leave ACRS. - */ - if ((read_byte(nec_priv, EXT_STATUS_1_REG) & - (RFD_HOLDOFF_STATUS_BIT | DATA_IN_STATUS_BIT | END_STATUS_BIT)) == - (DATA_IN_STATUS_BIT | END_STATUS_BIT)) { - write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR); - set_bit(RFD_HOLDOFF_BN, &nec_priv->state); - } else { - clear_bit(RFD_HOLDOFF_BN, &nec_priv->state); - } - } - spin_unlock_irqrestore(&board->spinlock, flags); -} - -static int fmh_gpib_accel_read(struct gpib_board *board, u8 *buffer, size_t length, - int *end, size_t *bytes_read) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - size_t remain = length; - size_t transfer_size; - int retval = 0; - size_t dma_nbytes; - unsigned long flags; - - smp_mb__before_atomic(); - clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME - smp_mb__after_atomic(); - *end = 0; - *bytes_read = 0; - - retval = wait_for_read(board); - if (retval < 0) - return retval; - - fmh_gpib_release_rfd_holdoff(board, e_priv); - while (remain > 0) { - transfer_size = (e_priv->dma_buffer_size < remain) ? - e_priv->dma_buffer_size : remain; - retval = fmh_gpib_dma_read(board, buffer, transfer_size, end, &dma_nbytes); - remain -= dma_nbytes; - buffer += dma_nbytes; - *bytes_read += dma_nbytes; - if (*end) - break; - if (retval < 0) - break; - if (need_resched()) - schedule(); - } - - spin_lock_irqsave(&board->spinlock, flags); - if (test_bit(RFD_HOLDOFF_BN, &nec_priv->state) == 0) { - write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR); - set_bit(RFD_HOLDOFF_BN, &nec_priv->state); - } - spin_unlock_irqrestore(&board->spinlock, flags); - - return retval; -} - -/* - * Read a chunk of data whose length is within the limits of the hardware's - * xfer counter. Called in a loop from fmh_gpib_fifo_read(). - */ -static int fmh_gpib_fifo_read_countable(struct gpib_board *board, u8 *buffer, - size_t length, int *end, size_t *bytes_read) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - int retval = 0; - - *bytes_read = 0; - *end = 0; - if (length == 0) - return 0; - - fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG); - fifos_write(e_priv, RX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG); - nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, 0); - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI); - - while (*bytes_read < length && *end == 0) { - int i; - - fifos_write(e_priv, RX_FIFO_HALF_FULL_INTERRUPT_ENABLE, FIFO_CONTROL_STATUS_REG); - retval = wait_for_rx_fifo_half_full_or_end(board); - if (retval < 0) - goto cleanup; - - for (i = 0; i < fmh_gpib_half_fifo_size(e_priv) && *end == 0; ++i) { - unsigned int data_value; - - data_value = fifos_read(e_priv, FIFO_DATA_REG); - buffer[(*bytes_read)++] = data_value & fifo_data_mask; - if (data_value & FIFO_DATA_EOI_FLAG) - *end = 1; - } - } - -cleanup: - // stop the transfer - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); - fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG); - - /* Manually read any dregs out of fifo. */ - while ((fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) & RX_FIFO_EMPTY) == 0) { - unsigned int data_value; - - if ((*bytes_read) >= length) { - dev_err(board->dev, "unexpected extra bytes in rx fifo, discarding! bytes_read=%d length=%d\n", - (int)(*bytes_read), (int)length); - break; - } - data_value = fifos_read(e_priv, FIFO_DATA_REG); - buffer[(*bytes_read)++] = data_value & fifo_data_mask; - if (data_value & FIFO_DATA_EOI_FLAG) - *end = 1; - } - - return retval; -} - -static int fmh_gpib_fifo_read(struct gpib_board *board, u8 *buffer, size_t length, - int *end, size_t *bytes_read) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - size_t remain = length; - size_t transfer_size; - int retval = 0; - size_t nbytes; - unsigned long flags; - - clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME - *end = 0; - *bytes_read = 0; - - /* - * Do a little prep with data in interrupt so that following wait_for_read() - * will wake up if a data byte is received. - */ - nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, HR_DIIE); - fmh_gpib_interrupt(0, board); - - retval = wait_for_read(board); - if (retval < 0) - return retval; - - fmh_gpib_release_rfd_holdoff(board, e_priv); - while (remain > 0) { - if (fifo_xfer_counter_mask < remain) { - // round transfer size to a multiple of half fifo size - transfer_size = (fifo_xfer_counter_mask / - fmh_gpib_half_fifo_size(e_priv)) * - fmh_gpib_half_fifo_size(e_priv); - } else { - transfer_size = remain; - } - retval = fmh_gpib_fifo_read_countable(board, buffer, transfer_size, end, &nbytes); - remain -= nbytes; - buffer += nbytes; - *bytes_read += nbytes; - if (*end) - break; - if (retval < 0) - break; - if (need_resched()) - schedule(); - } - - if (*end == 0) { - spin_lock_irqsave(&board->spinlock, flags); - write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR); - set_bit(RFD_HOLDOFF_BN, &nec_priv->state); - spin_unlock_irqrestore(&board->spinlock, flags); - } - - return retval; -} - -static struct gpib_interface fmh_gpib_unaccel_interface = { - .name = "fmh_gpib_unaccel", - .attach = fmh_gpib_attach_holdoff_all, - .detach = fmh_gpib_detach, - .read = fmh_gpib_read, - .write = fmh_gpib_write, - .command = fmh_gpib_command, - .take_control = fmh_gpib_take_control, - .go_to_standby = fmh_gpib_go_to_standby, - .request_system_control = fmh_gpib_request_system_control, - .interface_clear = fmh_gpib_interface_clear, - .remote_enable = fmh_gpib_remote_enable, - .enable_eos = fmh_gpib_enable_eos, - .disable_eos = fmh_gpib_disable_eos, - .parallel_poll = fmh_gpib_parallel_poll, - .parallel_poll_configure = fmh_gpib_parallel_poll_configure, - .parallel_poll_response = fmh_gpib_parallel_poll_response, - .local_parallel_poll_mode = fmh_gpib_local_parallel_poll_mode, - .line_status = fmh_gpib_line_status, - .update_status = fmh_gpib_update_status, - .primary_address = fmh_gpib_primary_address, - .secondary_address = fmh_gpib_secondary_address, - .serial_poll_response2 = fmh_gpib_serial_poll_response2, - .serial_poll_status = fmh_gpib_serial_poll_status, - .t1_delay = fmh_gpib_t1_delay, - .return_to_local = fmh_gpib_return_to_local, -}; - -static struct gpib_interface fmh_gpib_interface = { - .name = "fmh_gpib", - .attach = fmh_gpib_attach_holdoff_end, - .detach = fmh_gpib_detach, - .read = fmh_gpib_accel_read, - .write = fmh_gpib_accel_write, - .command = fmh_gpib_command, - .take_control = fmh_gpib_take_control, - .go_to_standby = fmh_gpib_go_to_standby, - .request_system_control = fmh_gpib_request_system_control, - .interface_clear = fmh_gpib_interface_clear, - .remote_enable = fmh_gpib_remote_enable, - .enable_eos = fmh_gpib_enable_eos, - .disable_eos = fmh_gpib_disable_eos, - .parallel_poll = fmh_gpib_parallel_poll, - .parallel_poll_configure = fmh_gpib_parallel_poll_configure, - .parallel_poll_response = fmh_gpib_parallel_poll_response, - .local_parallel_poll_mode = fmh_gpib_local_parallel_poll_mode, - .line_status = fmh_gpib_line_status, - .update_status = fmh_gpib_update_status, - .primary_address = fmh_gpib_primary_address, - .secondary_address = fmh_gpib_secondary_address, - .serial_poll_response2 = fmh_gpib_serial_poll_response2, - .serial_poll_status = fmh_gpib_serial_poll_status, - .t1_delay = fmh_gpib_t1_delay, - .return_to_local = fmh_gpib_return_to_local, -}; - -static struct gpib_interface fmh_gpib_pci_interface = { - .name = "fmh_gpib_pci", - .attach = fmh_gpib_pci_attach_holdoff_end, - .detach = fmh_gpib_pci_detach, - .read = fmh_gpib_fifo_read, - .write = fmh_gpib_fifo_write, - .command = fmh_gpib_command, - .take_control = fmh_gpib_take_control, - .go_to_standby = fmh_gpib_go_to_standby, - .request_system_control = fmh_gpib_request_system_control, - .interface_clear = fmh_gpib_interface_clear, - .remote_enable = fmh_gpib_remote_enable, - .enable_eos = fmh_gpib_enable_eos, - .disable_eos = fmh_gpib_disable_eos, - .parallel_poll = fmh_gpib_parallel_poll, - .parallel_poll_configure = fmh_gpib_parallel_poll_configure, - .parallel_poll_response = fmh_gpib_parallel_poll_response, - .local_parallel_poll_mode = fmh_gpib_local_parallel_poll_mode, - .line_status = fmh_gpib_line_status, - .update_status = fmh_gpib_update_status, - .primary_address = fmh_gpib_primary_address, - .secondary_address = fmh_gpib_secondary_address, - .serial_poll_response2 = fmh_gpib_serial_poll_response2, - .serial_poll_status = fmh_gpib_serial_poll_status, - .t1_delay = fmh_gpib_t1_delay, - .return_to_local = fmh_gpib_return_to_local, -}; - -static struct gpib_interface fmh_gpib_pci_unaccel_interface = { - .name = "fmh_gpib_pci_unaccel", - .attach = fmh_gpib_pci_attach_holdoff_all, - .detach = fmh_gpib_pci_detach, - .read = fmh_gpib_read, - .write = fmh_gpib_write, - .command = fmh_gpib_command, - .take_control = fmh_gpib_take_control, - .go_to_standby = fmh_gpib_go_to_standby, - .request_system_control = fmh_gpib_request_system_control, - .interface_clear = fmh_gpib_interface_clear, - .remote_enable = fmh_gpib_remote_enable, - .enable_eos = fmh_gpib_enable_eos, - .disable_eos = fmh_gpib_disable_eos, - .parallel_poll = fmh_gpib_parallel_poll, - .parallel_poll_configure = fmh_gpib_parallel_poll_configure, - .parallel_poll_response = fmh_gpib_parallel_poll_response, - .local_parallel_poll_mode = fmh_gpib_local_parallel_poll_mode, - .line_status = fmh_gpib_line_status, - .update_status = fmh_gpib_update_status, - .primary_address = fmh_gpib_primary_address, - .secondary_address = fmh_gpib_secondary_address, - .serial_poll_response2 = fmh_gpib_serial_poll_response2, - .serial_poll_status = fmh_gpib_serial_poll_status, - .t1_delay = fmh_gpib_t1_delay, - .return_to_local = fmh_gpib_return_to_local, -}; - -irqreturn_t fmh_gpib_internal_interrupt(struct gpib_board *board) -{ - unsigned int status0, status1, status2, ext_status_1, fifo_status; - struct fmh_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - int retval = IRQ_NONE; - - status0 = read_byte(nec_priv, ISR0_IMR0_REG); - status1 = read_byte(nec_priv, ISR1); - status2 = read_byte(nec_priv, ISR2); - fifo_status = fifos_read(priv, FIFO_CONTROL_STATUS_REG); - - if (status0 & IFC_INTERRUPT_BIT) { - push_gpib_event(board, EVENT_IFC); - retval = IRQ_HANDLED; - } - - if (nec7210_interrupt_have_status(board, nec_priv, status1, status2) == IRQ_HANDLED) - retval = IRQ_HANDLED; - - ext_status_1 = read_byte(nec_priv, EXT_STATUS_1_REG); - - if (ext_status_1 & DATA_IN_STATUS_BIT) - set_bit(READ_READY_BN, &nec_priv->state); - else - clear_bit(READ_READY_BN, &nec_priv->state); - - if (ext_status_1 & DATA_OUT_STATUS_BIT) - set_bit(WRITE_READY_BN, &nec_priv->state); - else - clear_bit(WRITE_READY_BN, &nec_priv->state); - - if (ext_status_1 & COMMAND_OUT_STATUS_BIT) - set_bit(COMMAND_READY_BN, &nec_priv->state); - else - clear_bit(COMMAND_READY_BN, &nec_priv->state); - - if (ext_status_1 & RFD_HOLDOFF_STATUS_BIT) - set_bit(RFD_HOLDOFF_BN, &nec_priv->state); - else - clear_bit(RFD_HOLDOFF_BN, &nec_priv->state); - - if (ext_status_1 & END_STATUS_BIT) { - /* - * only set RECEIVED_END while there is still a data - * byte sitting in the chip, to avoid spuriously - * setting it multiple times after it has been cleared - * during a read. - */ - if (ext_status_1 & DATA_IN_STATUS_BIT) - set_bit(RECEIVED_END_BN, &nec_priv->state); - } else { - clear_bit(RECEIVED_END_BN, &nec_priv->state); - } - - if ((fifo_status & TX_FIFO_HALF_EMPTY_INTERRUPT_IS_ENABLED) && - (fifo_status & TX_FIFO_HALF_EMPTY)) { - /* - * We really only want to clear the - * TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE bit in the - * FIFO_CONTROL_STATUS_REG. Since we are not being - * careful, this also has a side effect of disabling - * DMA requests and the RX fifo interrupt. That is - * fine though, since they should never be in use at - * the same time as the TX fifo interrupt. - */ - fifos_write(priv, 0x0, FIFO_CONTROL_STATUS_REG); - retval = IRQ_HANDLED; - } - - if ((fifo_status & RX_FIFO_HALF_FULL_INTERRUPT_IS_ENABLED) && - (fifo_status & RX_FIFO_HALF_FULL)) { - /* - * We really only want to clear the - * RX_FIFO_HALF_FULL_INTERRUPT_ENABLE bit in the - * FIFO_CONTROL_STATUS_REG. Since we are not being - * careful, this also has a side effect of disabling - * DMA requests and the TX fifo interrupt. That is - * fine though, since they should never be in use at - * the same time as the RX fifo interrupt. - */ - fifos_write(priv, 0x0, FIFO_CONTROL_STATUS_REG); - retval = IRQ_HANDLED; - } - - if (retval == IRQ_HANDLED) - wake_up_interruptible(&board->wait); - - return retval; -} - -irqreturn_t fmh_gpib_interrupt(int irq, void *arg) -{ - struct gpib_board *board = arg; - unsigned long flags; - irqreturn_t retval; - - spin_lock_irqsave(&board->spinlock, flags); - retval = fmh_gpib_internal_interrupt(board); - spin_unlock_irqrestore(&board->spinlock, flags); - return retval; -} - -static int fmh_gpib_allocate_private(struct gpib_board *board) -{ - struct fmh_priv *priv; - - board->private_data = kmalloc(sizeof(struct fmh_priv), GFP_KERNEL); - if (!board->private_data) - return -ENOMEM; - priv = board->private_data; - memset(priv, 0, sizeof(struct fmh_priv)); - init_nec7210_private(&priv->nec7210_priv); - priv->dma_buffer_size = 0x800; - priv->dma_buffer = kmalloc(priv->dma_buffer_size, GFP_KERNEL); - if (!priv->dma_buffer) - return -ENOMEM; - return 0; -} - -static void fmh_gpib_generic_detach(struct gpib_board *board) -{ - if (board->private_data) { - struct fmh_priv *e_priv = board->private_data; - - kfree(e_priv->dma_buffer); - kfree(board->private_data); - board->private_data = NULL; - } - if (board->dev) - dev_set_drvdata(board->dev, NULL); -} - -// generic part of attach functions -static int fmh_gpib_generic_attach(struct gpib_board *board) -{ - struct fmh_priv *e_priv; - struct nec7210_priv *nec_priv; - int retval; - - board->status = 0; - - retval = fmh_gpib_allocate_private(board); - if (retval < 0) - return retval; - e_priv = board->private_data; - nec_priv = &e_priv->nec7210_priv; - nec_priv->read_byte = gpib_cs_read_byte; - nec_priv->write_byte = gpib_cs_write_byte; - nec_priv->offset = 1; - nec_priv->type = CB7210; - return 0; -} - -static int fmh_gpib_config_dma(struct gpib_board *board, int output) -{ - struct fmh_priv *e_priv = board->private_data; - struct dma_slave_config config; - - config.device_fc = true; - - if (e_priv->dma_burst_length < 1) { - config.src_maxburst = 1; - config.dst_maxburst = 1; - } else { - config.src_maxburst = e_priv->dma_burst_length; - config.dst_maxburst = e_priv->dma_burst_length; - } - - config.src_addr_width = 1; - config.dst_addr_width = 1; - - if (output) { - config.direction = DMA_MEM_TO_DEV; - config.src_addr = 0; - config.dst_addr = e_priv->dma_port_res->start + FIFO_DATA_REG * fifo_reg_offset; - } else { - config.direction = DMA_DEV_TO_MEM; - config.src_addr = e_priv->dma_port_res->start + FIFO_DATA_REG * fifo_reg_offset; - config.dst_addr = 0; - } - return dmaengine_slave_config(e_priv->dma_channel, &config); -} - -static int fmh_gpib_init(struct fmh_priv *e_priv, struct gpib_board *board, int handshake_mode) -{ - struct nec7210_priv *nec_priv = &e_priv->nec7210_priv; - unsigned long flags; - unsigned int fifo_status_bits; - - fifos_write(e_priv, RX_FIFO_CLEAR | TX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG); - - nec7210_board_reset(nec_priv, board); - write_byte(nec_priv, AUX_LO_SPEED, AUXMR); - nec7210_set_handshake_mode(board, nec_priv, handshake_mode); - - /* Hueristically check if hardware supports fifo half full/empty interrupts */ - fifo_status_bits = fifos_read(e_priv, FIFO_CONTROL_STATUS_REG); - e_priv->supports_fifo_interrupts = (fifo_status_bits & TX_FIFO_EMPTY) && - (fifo_status_bits & TX_FIFO_HALF_EMPTY); - - nec7210_board_online(nec_priv, board); - - write_byte(nec_priv, IFC_INTERRUPT_ENABLE_BIT | ATN_INTERRUPT_ENABLE_BIT, ISR0_IMR0_REG); - - spin_lock_irqsave(&board->spinlock, flags); - write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR); - set_bit(RFD_HOLDOFF_BN, &nec_priv->state); - spin_unlock_irqrestore(&board->spinlock, flags); - return 0; -} - -/* Match callback for driver_find_device */ -static int fmh_gpib_device_match(struct device *dev, const void *data) -{ - const struct gpib_board_config *config = data; - - if (dev_get_drvdata(dev)) - return 0; - - if (gpib_match_device_path(dev, config->device_path) == 0) - return 0; - - // driver doesn't support selection by serial number - if (config->serial_number) - return 0; - - dev_dbg(dev, "matched: %s\n", of_node_full_name(dev_of_node((dev)))); - return 1; -} - -static int fmh_gpib_attach_impl(struct gpib_board *board, const struct gpib_board_config *config, - unsigned int handshake_mode, int acquire_dma) -{ - struct fmh_priv *e_priv; - struct nec7210_priv *nec_priv; - int retval; - int irq; - struct resource *res; - struct platform_device *pdev; - - board->dev = driver_find_device(&fmh_gpib_platform_driver.driver, - NULL, (const void *)config, &fmh_gpib_device_match); - if (!board->dev) { - dev_err(board->gpib_dev, "No matching fmh_gpib_core device was found, attach failed."); - return -ENODEV; - } - // currently only used to mark the device as already attached - dev_set_drvdata(board->dev, board); - pdev = to_platform_device(board->dev); - - retval = fmh_gpib_generic_attach(board); - if (retval) - return retval; - - e_priv = board->private_data; - nec_priv = &e_priv->nec7210_priv; - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpib_control_status"); - if (!res) { - dev_err(board->dev, "Unable to locate mmio resource\n"); - return -ENODEV; - } - - if (request_mem_region(res->start, - resource_size(res), - pdev->name) == NULL) { - dev_err(board->dev, "cannot claim registers\n"); - return -ENXIO; - } - e_priv->gpib_iomem_res = res; - - nec_priv->mmiobase = ioremap(e_priv->gpib_iomem_res->start, - resource_size(e_priv->gpib_iomem_res)); - if (!nec_priv->mmiobase) { - dev_err(board->dev, "Could not map I/O memory\n"); - return -ENOMEM; - } - dev_dbg(board->dev, "iobase %pr remapped to %p\n", - e_priv->gpib_iomem_res, nec_priv->mmiobase); - - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma_fifos"); - if (!res) { - dev_err(board->dev, "Unable to locate mmio resource for gpib dma port\n"); - return -ENODEV; - } - if (request_mem_region(res->start, - resource_size(res), - pdev->name) == NULL) { - dev_err(board->dev, "cannot claim registers\n"); - return -ENXIO; - } - e_priv->dma_port_res = res; - e_priv->fifo_base = ioremap(e_priv->dma_port_res->start, - resource_size(e_priv->dma_port_res)); - if (!e_priv->fifo_base) { - dev_err(board->dev, "Could not map I/O memory for fifos\n"); - return -ENOMEM; - } - dev_dbg(board->dev, "dma fifos 0x%lx remapped to %p, length=%ld\n", - (unsigned long)e_priv->dma_port_res->start, e_priv->fifo_base, - (unsigned long)resource_size(e_priv->dma_port_res)); - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return -EBUSY; - retval = request_irq(irq, fmh_gpib_interrupt, IRQF_SHARED, pdev->name, board); - if (retval) { - dev_err(board->dev, - "cannot register interrupt handler err=%d\n", - retval); - return retval; - } - e_priv->irq = irq; - - if (acquire_dma) { - e_priv->dma_channel = dma_request_slave_channel(board->dev, "rxtx"); - if (!e_priv->dma_channel) { - dev_err(board->dev, "failed to acquire dma channel \"rxtx\".\n"); - return -EIO; - } - } - /* - * in the future we might want to know the half-fifo size - * (dma_burst_length) even when not using dma, so go ahead an - * initialize it unconditionally. - */ - e_priv->dma_burst_length = fifos_read(e_priv, FIFO_MAX_BURST_LENGTH_REG) & - fifo_max_burst_length_mask; - - return fmh_gpib_init(e_priv, board, handshake_mode); -} - -int fmh_gpib_attach_holdoff_all(struct gpib_board *board, const struct gpib_board_config *config) -{ - return fmh_gpib_attach_impl(board, config, HR_HLDA, 0); -} - -int fmh_gpib_attach_holdoff_end(struct gpib_board *board, const struct gpib_board_config *config) -{ - return fmh_gpib_attach_impl(board, config, HR_HLDE, 1); -} - -void fmh_gpib_detach(struct gpib_board *board) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (e_priv) { - if (e_priv->dma_channel) - dma_release_channel(e_priv->dma_channel); - nec_priv = &e_priv->nec7210_priv; - - if (e_priv->irq) - free_irq(e_priv->irq, board); - if (e_priv->fifo_base) - fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG); - if (nec_priv->mmiobase) { - write_byte(nec_priv, 0, ISR0_IMR0_REG); - nec7210_board_reset(nec_priv, board); - } - if (e_priv->fifo_base) - iounmap(e_priv->fifo_base); - if (nec_priv->mmiobase) - iounmap(nec_priv->mmiobase); - if (e_priv->dma_port_res) { - release_mem_region(e_priv->dma_port_res->start, - resource_size(e_priv->dma_port_res)); - } - if (e_priv->gpib_iomem_res) - release_mem_region(e_priv->gpib_iomem_res->start, - resource_size(e_priv->gpib_iomem_res)); - } - fmh_gpib_generic_detach(board); - - if (board->dev) { - put_device(board->dev); - board->dev = NULL; - } -} - -static int fmh_gpib_pci_attach_impl(struct gpib_board *board, - const struct gpib_board_config *config, - unsigned int handshake_mode) -{ - struct fmh_priv *e_priv; - struct nec7210_priv *nec_priv; - int retval; - struct pci_dev *pci_device; - - retval = fmh_gpib_generic_attach(board); - if (retval) - return retval; - - e_priv = board->private_data; - nec_priv = &e_priv->nec7210_priv; - - // find board - pci_device = gpib_pci_get_device(config, BOGUS_PCI_VENDOR_ID_FLUKE, - BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER, NULL); - if (!pci_device) { - dev_err(board->gpib_dev, "No matching fmh_gpib_core pci device was found, attach failed."); - return -ENODEV; - } - board->dev = &pci_device->dev; - - // bladerunner prototype has offset of 4 between gpib control/status registers - nec_priv->offset = 4; - - if (pci_enable_device(pci_device)) { - dev_err(board->dev, "error enabling pci device\n"); - return -EIO; - } - if (pci_request_regions(pci_device, KBUILD_MODNAME)) { - dev_err(board->dev, "pci_request_regions failed\n"); - return -EIO; - } - e_priv->gpib_iomem_res = &pci_device->resource[gpib_control_status_pci_resource_index]; - e_priv->dma_port_res = &pci_device->resource[gpib_fifo_pci_resource_index]; - - nec_priv->mmiobase = ioremap(pci_resource_start(pci_device, - gpib_control_status_pci_resource_index), - pci_resource_len(pci_device, - gpib_control_status_pci_resource_index)); - dev_dbg(board->dev, "base address for gpib control/status registers remapped to 0x%p\n", - nec_priv->mmiobase); - - if (e_priv->dma_port_res->flags & IORESOURCE_MEM) { - e_priv->fifo_base = ioremap(pci_resource_start(pci_device, - gpib_fifo_pci_resource_index), - pci_resource_len(pci_device, - gpib_fifo_pci_resource_index)); - dev_dbg(board->dev, "base address for gpib fifo registers remapped to 0x%p\n", - e_priv->fifo_base); - } else { - e_priv->fifo_base = NULL; - dev_dbg(board->dev, "hardware has no gpib fifo registers.\n"); - } - - if (pci_device->irq) { - retval = request_irq(pci_device->irq, fmh_gpib_interrupt, IRQF_SHARED, - KBUILD_MODNAME, board); - if (retval) { - dev_err(board->dev, "cannot register interrupt handler err=%d\n", retval); - return retval; - } - } - e_priv->irq = pci_device->irq; - - e_priv->dma_burst_length = fifos_read(e_priv, FIFO_MAX_BURST_LENGTH_REG) & - fifo_max_burst_length_mask; - - return fmh_gpib_init(e_priv, board, handshake_mode); -} - -int fmh_gpib_pci_attach_holdoff_all(struct gpib_board *board, - const struct gpib_board_config *config) -{ - return fmh_gpib_pci_attach_impl(board, config, HR_HLDA); -} - -int fmh_gpib_pci_attach_holdoff_end(struct gpib_board *board, - const struct gpib_board_config *config) -{ - int retval; - struct fmh_priv *e_priv; - - retval = fmh_gpib_pci_attach_impl(board, config, HR_HLDE); - e_priv = board->private_data; - if (retval == 0 && e_priv && e_priv->supports_fifo_interrupts == 0) { - dev_err(board->gpib_dev, "your fmh_gpib_core does not appear to support fifo interrupts. Try the fmh_gpib_pci_unaccel board type instead."); - return -EIO; - } - return retval; -} - -void fmh_gpib_pci_detach(struct gpib_board *board) -{ - struct fmh_priv *e_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (e_priv) { - nec_priv = &e_priv->nec7210_priv; - - if (e_priv->irq) - free_irq(e_priv->irq, board); - if (e_priv->fifo_base) - fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG); - if (nec_priv->mmiobase) { - write_byte(nec_priv, 0, ISR0_IMR0_REG); - nec7210_board_reset(nec_priv, board); - } - if (e_priv->fifo_base) - iounmap(e_priv->fifo_base); - if (nec_priv->mmiobase) - iounmap(nec_priv->mmiobase); - if (e_priv->dma_port_res || e_priv->gpib_iomem_res) - pci_release_regions(to_pci_dev(board->dev)); - if (board->dev) - pci_dev_put(to_pci_dev(board->dev)); - } - fmh_gpib_generic_detach(board); -} - -static int fmh_gpib_platform_probe(struct platform_device *pdev) -{ - return 0; -} - -static const struct of_device_id fmh_gpib_of_match[] = { - { .compatible = "fmhess,fmh_gpib_core"}, - { {0} } -}; -MODULE_DEVICE_TABLE(of, fmh_gpib_of_match); - -static struct platform_driver fmh_gpib_platform_driver = { - .driver = { - .name = DRV_NAME, - .of_match_table = fmh_gpib_of_match, - }, - .probe = &fmh_gpib_platform_probe -}; - -static int fmh_gpib_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - return 0; -} - -static const struct pci_device_id fmh_gpib_pci_match[] = { - { BOGUS_PCI_VENDOR_ID_FLUKE, BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER, 0, 0, 0 }, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, fmh_gpib_pci_match); - -static struct pci_driver fmh_gpib_pci_driver = { - .name = DRV_NAME, - .id_table = fmh_gpib_pci_match, - .probe = &fmh_gpib_pci_probe -}; - -static int __init fmh_gpib_init_module(void) -{ - int result; - - result = platform_driver_register(&fmh_gpib_platform_driver); - if (result) { - pr_err("platform_driver_register failed: error = %d\n", result); - return result; - } - - result = pci_register_driver(&fmh_gpib_pci_driver); - if (result) { - pr_err("pci_register_driver failed: error = %d\n", result); - goto err_pci_driver; - } - - result = gpib_register_driver(&fmh_gpib_unaccel_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_unaccel; - } - - result = gpib_register_driver(&fmh_gpib_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_interface; - } - - result = gpib_register_driver(&fmh_gpib_pci_unaccel_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_pci_unaccel; - } - - result = gpib_register_driver(&fmh_gpib_pci_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_pci; - } - - return 0; - -err_pci: - gpib_unregister_driver(&fmh_gpib_pci_unaccel_interface); -err_pci_unaccel: - gpib_unregister_driver(&fmh_gpib_interface); -err_interface: - gpib_unregister_driver(&fmh_gpib_unaccel_interface); -err_unaccel: - pci_unregister_driver(&fmh_gpib_pci_driver); -err_pci_driver: - platform_driver_unregister(&fmh_gpib_platform_driver); - - return result; -} - -static void __exit fmh_gpib_exit_module(void) -{ - gpib_unregister_driver(&fmh_gpib_pci_interface); - gpib_unregister_driver(&fmh_gpib_pci_unaccel_interface); - gpib_unregister_driver(&fmh_gpib_unaccel_interface); - gpib_unregister_driver(&fmh_gpib_interface); - - pci_unregister_driver(&fmh_gpib_pci_driver); - platform_driver_unregister(&fmh_gpib_platform_driver); -} - -module_init(fmh_gpib_init_module); -module_exit(fmh_gpib_exit_module); diff --git a/drivers/staging/gpib/fmh_gpib/fmh_gpib.h b/drivers/staging/gpib/fmh_gpib/fmh_gpib.h deleted file mode 100644 index e7602d7e1401..000000000000 --- a/drivers/staging/gpib/fmh_gpib/fmh_gpib.h +++ /dev/null @@ -1,177 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * Author: Frank Mori Hess <fmh6jj@gmail.com> - * Copyright: (C) 2006, 2010, 2015 Fluke Corporation - * (C) 2017 Frank Mori Hess - ***************************************************************************/ - -#include <linux/dmaengine.h> -#include <linux/ioport.h> -#include <linux/pci.h> -#include <linux/io.h> -#include "nec7210.h" - -static const int fifo_reg_offset = 2; - -static const int gpib_control_status_pci_resource_index; -static const int gpib_fifo_pci_resource_index = 1; - -/* We don't have a real pci vendor/device id, the following will need to be - * patched to match prototype hardware. - */ -#define BOGUS_PCI_VENDOR_ID_FLUKE 0xffff -#define BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER 0x0 - -struct fmh_priv { - struct nec7210_priv nec7210_priv; - struct resource *gpib_iomem_res; - struct resource *write_transfer_counter_res; - struct resource *dma_port_res; - int irq; - struct dma_chan *dma_channel; - u8 *dma_buffer; - int dma_buffer_size; - int dma_burst_length; - void __iomem *fifo_base; - unsigned supports_fifo_interrupts : 1; -}; - -static inline int fmh_gpib_half_fifo_size(struct fmh_priv *priv) -{ - return priv->dma_burst_length; -} - -// registers beyond the nec7210 register set -enum fmh_gpib_regs { - EXT_STATUS_1_REG = 0x9, - STATE1_REG = 0xc, - ISR0_IMR0_REG = 0xe, - BUS_STATUS_REG = 0xf -}; - -/* IMR0 -- Interrupt Mode Register 0 */ -enum imr0_bits { - ATN_INTERRUPT_ENABLE_BIT = 0x4, - IFC_INTERRUPT_ENABLE_BIT = 0x8 -}; - -/* ISR0 -- Interrupt Status Register 0 */ -enum isr0_bits { - ATN_INTERRUPT_BIT = 0x4, - IFC_INTERRUPT_BIT = 0x8 -}; - -enum state1_bits { - SOURCE_HANDSHAKE_SIDS_BITS = 0x0, /* source idle state */ - SOURCE_HANDSHAKE_SGNS_BITS = 0x1, /* source generate state */ - SOURCE_HANDSHAKE_SDYS_BITS = 0x2, /* source delay state */ - SOURCE_HANDSHAKE_STRS_BITS = 0x5, /* source transfer state */ - SOURCE_HANDSHAKE_MASK = 0x7 -}; - -enum fmh_gpib_auxmr_bits { - AUX_I_REG = 0xe0, -}; - -enum aux_reg_i_bits { - LOCAL_PPOLL_MODE_BIT = 0x4 -}; - -enum ext_status_1_bits { - DATA_IN_STATUS_BIT = 0x01, - DATA_OUT_STATUS_BIT = 0x02, - COMMAND_OUT_STATUS_BIT = 0x04, - RFD_HOLDOFF_STATUS_BIT = 0x08, - END_STATUS_BIT = 0x10 -}; - -/* dma fifo reg and bits */ -enum dma_fifo_regs { - FIFO_DATA_REG = 0x0, - FIFO_CONTROL_STATUS_REG = 0x1, - FIFO_XFER_COUNTER_REG = 0x2, - FIFO_MAX_BURST_LENGTH_REG = 0x3 -}; - -enum fifo_data_bits { - FIFO_DATA_EOI_FLAG = 0x100 -}; - -enum fifo_control_bits { - TX_FIFO_DMA_REQUEST_ENABLE = 0x0001, - TX_FIFO_CLEAR = 0x0002, - TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE = 0x0008, - RX_FIFO_DMA_REQUEST_ENABLE = 0x0100, - RX_FIFO_CLEAR = 0x0200, - RX_FIFO_HALF_FULL_INTERRUPT_ENABLE = 0x0800 -}; - -enum fifo_status_bits { - TX_FIFO_EMPTY = 0x0001, - TX_FIFO_FULL = 0x0002, - TX_FIFO_HALF_EMPTY = 0x0004, - TX_FIFO_HALF_EMPTY_INTERRUPT_IS_ENABLED = 0x0008, - TX_FIFO_DMA_REQUEST_IS_ENABLED = 0x0010, - RX_FIFO_EMPTY = 0x0100, - RX_FIFO_FULL = 0x0200, - RX_FIFO_HALF_FULL = 0x0400, - RX_FIFO_HALF_FULL_INTERRUPT_IS_ENABLED = 0x0800, - RX_FIFO_DMA_REQUEST_IS_ENABLED = 0x1000 -}; - -static const unsigned int fifo_data_mask = 0x00ff; -static const unsigned int fifo_xfer_counter_mask = 0x0fff; -static const unsigned int fifo_max_burst_length_mask = 0x00ff; - -static inline u8 gpib_cs_read_byte(struct nec7210_priv *nec_priv, - unsigned int register_num) -{ - return readb(nec_priv->mmiobase + register_num * nec_priv->offset); -} - -static inline void gpib_cs_write_byte(struct nec7210_priv *nec_priv, u8 data, - unsigned int register_num) -{ - writeb(data, nec_priv->mmiobase + register_num * nec_priv->offset); -} - -static inline uint16_t fifos_read(struct fmh_priv *fmh_priv, int register_num) -{ - if (!fmh_priv->fifo_base) - return 0; - return readw(fmh_priv->fifo_base + register_num * fifo_reg_offset); -} - -static inline void fifos_write(struct fmh_priv *fmh_priv, uint16_t data, int register_num) -{ - if (!fmh_priv->fifo_base) - return; - writew(data, fmh_priv->fifo_base + register_num * fifo_reg_offset); -} - -enum bus_status_bits { - BSR_ATN_BIT = 0x01, - BSR_EOI_BIT = 0x02, - BSR_SRQ_BIT = 0x04, - BSR_IFC_BIT = 0x08, - BSR_REN_BIT = 0x10, - BSR_DAV_BIT = 0x20, - BSR_NRFD_BIT = 0x40, - BSR_NDAC_BIT = 0x80, -}; - -enum fmh_gpib_aux_cmds { - /* AUX_RTL2 is an auxiliary command which causes the cb7210 to assert - * (and keep asserted) the local rtl message. This is used in conjunction - * with the normal nec7210 AUX_RTL command, which - * pulses the rtl message, having the effect of clearing rtl if it was left - * asserted by AUX_RTL2. - */ - AUX_RTL2 = 0x0d, - AUX_RFD_HOLDOFF_ASAP = 0x15, - AUX_REQT = 0x18, - AUX_REQF = 0x19, - AUX_LO_SPEED = 0x40, - AUX_HI_SPEED = 0x41 -}; diff --git a/drivers/staging/gpib/gpio/Makefile b/drivers/staging/gpib/gpio/Makefile deleted file mode 100644 index 00ea52abdda7..000000000000 --- a/drivers/staging/gpib/gpio/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -obj-$(CONFIG_GPIB_GPIO) += gpib_bitbang.o - - diff --git a/drivers/staging/gpib/gpio/gpib_bitbang.c b/drivers/staging/gpib/gpio/gpib_bitbang.c deleted file mode 100644 index 374cd61355e9..000000000000 --- a/drivers/staging/gpib/gpio/gpib_bitbang.c +++ /dev/null @@ -1,1469 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/************************************************************************* - * This code has been developed at the Institute of Sensor and Actuator * - * Systems (Technical University of Vienna, Austria) to enable the GPIO * - * lines (e.g. of a raspberry pi) to function as a GPIO master device * - * * - * authors : Thomas Klima * - * Marcello Carla' * - * Dave Penkler * - * * - * copyright : (C) 2016 Thomas Klima * - * * - *************************************************************************/ - -/* - * limitations: - * works only on RPi - * cannot function as non-CIC system controller with SN7516x because - * SN75161B cannot simultaneously make ATN input with IFC and REN as - * outputs. - * not implemented: - * parallel poll - * return2local - * device support (non master operation) - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define NAME KBUILD_MODNAME - -#define ENABLE_IRQ(IRQ, TYPE) irq_set_irq_type(IRQ, TYPE) -#define DISABLE_IRQ(IRQ) irq_set_irq_type(IRQ, IRQ_TYPE_NONE) - -/* - * Debug print levels: - * 0 = load/unload info and errors that make the driver fail; - * 1 = + warnings for unforeseen events that may break the current - * operation and lead to a timeout, but do not affect the - * driver integrity (mainly unexpected interrupts); - * 2 = + trace of function calls; - * 3 = + trace of protocol codes; - * 4 = + trace of interrupt operation. - */ -#define dbg_printk(level, frm, ...) \ - do { if (debug >= (level)) \ - dev_dbg(board->gpib_dev, frm, ## __VA_ARGS__); } \ - while (0) - -#define LINVAL gpiod_get_value(DAV), \ - gpiod_get_value(NRFD), \ - gpiod_get_value(NDAC), \ - gpiod_get_value(SRQ) -#define LINFMT "DAV: %d NRFD:%d NDAC: %d SRQ: %d" - -#include "gpibP.h" -#include "gpib_state_machines.h" -#include <linux/sched.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/gpio/consumer.h> -#include <linux/gpio/driver.h> -#include <linux/gpio/machine.h> -#include <linux/gpio.h> -#include <linux/irq.h> - -static int sn7516x_used = 1, sn7516x; -module_param(sn7516x_used, int, 0660); - -#define PINMAP_0 "elektronomikon" -#define PINMAP_1 "gpib4pi-1.1" -#define PINMAP_2 "yoga" -static char *pin_map = PINMAP_0; -module_param(pin_map, charp, 0660); -MODULE_PARM_DESC(pin_map, " valid values: " PINMAP_0 " " PINMAP_1 " " PINMAP_2); - -/********************************************** - * Signal pairing and pin wiring between the * - * Raspberry-Pi connector and the GPIB bus * - * * - * signal pin wiring * - * GPIB Pi-gpio GPIB -> RPi * - ********************************************** - */ -enum lines_t { - D01_pin_nr = 20, /* 1 -> 38 */ - D02_pin_nr = 26, /* 2 -> 37 */ - D03_pin_nr = 16, /* 3 -> 36 */ - D04_pin_nr = 19, /* 4 -> 35 */ - D05_pin_nr = 13, /* 13 -> 33 */ - D06_pin_nr = 12, /* 14 -> 32 */ - D07_pin_nr = 6, /* 15 -> 31 */ - D08_pin_nr = 5, /* 16 -> 29 */ - EOI_pin_nr = 9, /* 5 -> 21 */ - DAV_pin_nr = 10, /* 6 -> 19 */ - NRFD_pin_nr = 24, /* 7 -> 18 */ - NDAC_pin_nr = 23, /* 8 -> 16 */ - IFC_pin_nr = 22, /* 9 -> 15 */ - SRQ_pin_nr = 11, /* 10 -> 23 */ - _ATN_pin_nr = 25, /* 11 -> 22 */ - REN_pin_nr = 27, /* 17 -> 13 */ -/* - * GROUND PINS - * 12,18,19,20,21,22,23,24 => 14,20,25,30,34,39 - */ - -/* - * These lines are used to control the external - * SN75160/161 driver chips when used. - * When not used there is reduced fan out; - * currently tested with up to 4 devices. - */ - -/* Pi GPIO RPI 75161B 75160B Description */ - PE_pin_nr = 7, /* 26 -> nc 11 Pullup Enable */ - DC_pin_nr = 8, /* 24 -> 12 nc Direction control */ - TE_pin_nr = 18, /* 12 -> 2 1 Talk Enable */ - ACT_LED_pin_nr = 4, /* 7 -> LED */ - -/* YOGA adapter uses different pinout to ease layout */ - YOGA_D03_pin_nr = 13, - YOGA_D04_pin_nr = 12, - YOGA_D05_pin_nr = 21, - YOGA_D06_pin_nr = 19, -}; - -/* - * GPIO descriptors and pins - WARNING: STRICTLY KEEP ITEMS ORDER - */ - -#define GPIB_PINS 16 -#define SN7516X_PINS 4 -#define NUM_PINS (GPIB_PINS + SN7516X_PINS) - -#define ACT_LED_ON do { \ - if (ACT_LED) \ - gpiod_direction_output(ACT_LED, 1); \ - } while (0) -#define ACT_LED_OFF do { \ - if (ACT_LED) \ - gpiod_direction_output(ACT_LED, 0); \ - } while (0) - -static struct gpio_desc *all_descriptors[GPIB_PINS + SN7516X_PINS]; - -#define D01 all_descriptors[0] -#define D02 all_descriptors[1] -#define D03 all_descriptors[2] -#define D04 all_descriptors[3] -#define D05 all_descriptors[4] -#define D06 all_descriptors[5] -#define D07 all_descriptors[6] -#define D08 all_descriptors[7] - -#define EOI all_descriptors[8] -#define NRFD all_descriptors[9] -#define IFC all_descriptors[10] -#define _ATN all_descriptors[11] -#define REN all_descriptors[12] -#define DAV all_descriptors[13] -#define NDAC all_descriptors[14] -#define SRQ all_descriptors[15] - -#define PE all_descriptors[16] -#define DC all_descriptors[17] -#define TE all_descriptors[18] -#define ACT_LED all_descriptors[19] - -/* YOGA adapter uses a global enable for the buffer chips, re-using the TE pin */ -#define YOGA_ENABLE TE - -static int gpios_vector[] = { - D01_pin_nr, - D02_pin_nr, - D03_pin_nr, - D04_pin_nr, - D05_pin_nr, - D06_pin_nr, - D07_pin_nr, - D08_pin_nr, - - EOI_pin_nr, - NRFD_pin_nr, - IFC_pin_nr, - _ATN_pin_nr, - REN_pin_nr, - DAV_pin_nr, - NDAC_pin_nr, - SRQ_pin_nr, - - PE_pin_nr, - DC_pin_nr, - TE_pin_nr, - ACT_LED_pin_nr -}; - -/* Lookup table for general GPIOs */ - -static struct gpiod_lookup_table gpib_gpio_table_1 = { - // for bcm2835/6 - .dev_id = "", // device id of board device - .table = { - GPIO_LOOKUP_IDX("GPIO_GCLK", U16_MAX, NULL, 4, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO5", U16_MAX, NULL, 5, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO6", U16_MAX, NULL, 6, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("SPI_CE1_N", U16_MAX, NULL, 7, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("SPI_CE0_N", U16_MAX, NULL, 8, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("SPI_MISO", U16_MAX, NULL, 9, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("SPI_MOSI", U16_MAX, NULL, 10, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("SPI_SCLK", U16_MAX, NULL, 11, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO12", U16_MAX, NULL, 12, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO13", U16_MAX, NULL, 13, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO16", U16_MAX, NULL, 16, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO17", U16_MAX, NULL, 17, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO18", U16_MAX, NULL, 18, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO19", U16_MAX, NULL, 19, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO20", U16_MAX, NULL, 20, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO21", U16_MAX, NULL, 21, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO22", U16_MAX, NULL, 22, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO23", U16_MAX, NULL, 23, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO24", U16_MAX, NULL, 24, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO25", U16_MAX, NULL, 25, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO26", U16_MAX, NULL, 26, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO27", U16_MAX, NULL, 27, GPIO_ACTIVE_HIGH), - { } - }, -}; - -static struct gpiod_lookup_table gpib_gpio_table_0 = { - .dev_id = "", // device id of board device - .table = { - // for bcm27xx based pis (b b+ 2b 3b 3b+ 4 5) - GPIO_LOOKUP_IDX("GPIO4", U16_MAX, NULL, 4, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO5", U16_MAX, NULL, 5, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO6", U16_MAX, NULL, 6, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO7", U16_MAX, NULL, 7, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO8", U16_MAX, NULL, 8, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO9", U16_MAX, NULL, 9, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO10", U16_MAX, NULL, 10, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO11", U16_MAX, NULL, 11, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO12", U16_MAX, NULL, 12, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO13", U16_MAX, NULL, 13, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO16", U16_MAX, NULL, 16, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO17", U16_MAX, NULL, 17, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO18", U16_MAX, NULL, 18, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO19", U16_MAX, NULL, 19, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO20", U16_MAX, NULL, 20, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO21", U16_MAX, NULL, 21, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO22", U16_MAX, NULL, 22, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO23", U16_MAX, NULL, 23, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO24", U16_MAX, NULL, 24, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO25", U16_MAX, NULL, 25, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO26", U16_MAX, NULL, 26, GPIO_ACTIVE_HIGH), - GPIO_LOOKUP_IDX("GPIO27", U16_MAX, NULL, 27, GPIO_ACTIVE_HIGH), - { } - }, -}; - -static struct gpiod_lookup_table *lookup_tables[] = { - &gpib_gpio_table_0, - &gpib_gpio_table_1, - NULL -}; - -/* struct which defines private_data for gpio driver */ - -struct bb_priv { - int irq_NRFD; - int irq_NDAC; - int irq_DAV; - int irq_SRQ; - int dav_mode; /* dav interrupt mode 0/1 -> edge/levels */ - int nrfd_mode; /* nrfd interrupt mode 0/1 -> edge/levels */ - int ndac_mode; /* nrfd interrupt mode 0/1 -> edge/levels */ - int dav_tx; /* keep trace of DAV status while sending */ - int dav_rx; /* keep trace of DAV status while receiving */ - u8 eos; /* eos character */ - short eos_flags; /* eos mode */ - short eos_check; /* eos check required in current operation ... */ - short eos_check_8; /* ... with byte comparison */ - short eos_mask_7; /* ... with 7 bit masked character */ - short int end; - int request; - int count; - int direction; - int t1_delay; - u8 *rbuf; - u8 *wbuf; - int end_flag; - int r_busy; /* 0==idle 1==busy */ - int w_busy; - int write_done; - int cmd; /* 1 = cmd write in progress */ - size_t w_cnt; - size_t length; - u8 *w_buf; - spinlock_t rw_lock; /* protect mods to rw_lock */ - int phase; - int ndac_idle; - int ndac_seq; - int nrfd_idle; - int nrfd_seq; - int dav_seq; - long all_irqs; - int dav_idle; - - enum talker_function_state talker_state; - enum listener_function_state listener_state; -}; - -static inline long usec_diff(struct timespec64 *a, struct timespec64 *b); -static void bb_buffer_print(struct gpib_board *board, unsigned char *buffer, size_t length, - int cmd, int eoi); -static void set_data_lines(u8 byte); -static u8 get_data_lines(void); -static void set_data_lines_input(void); -static void set_data_lines_output(void); -static inline int check_for_eos(struct bb_priv *priv, u8 byte); -static void set_atn(struct gpib_board *board, int atn_asserted); - -static inline void SET_DIR_WRITE(struct bb_priv *priv); -static inline void SET_DIR_READ(struct bb_priv *priv); - -#define DIR_READ 0 -#define DIR_WRITE 1 - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB helper functions for bitbanging I/O"); - -/**** global variables ****/ -static int debug; -module_param(debug, int, 0644); - -static char printable(char x) -{ - if (x < 32 || x > 126) - return ' '; - return x; -} - -/*************************************************************************** - * * - * READ * - * * - ***************************************************************************/ - -static int bb_read(struct gpib_board *board, u8 *buffer, size_t length, - int *end, size_t *bytes_read) -{ - struct bb_priv *priv = board->private_data; - unsigned long flags; - int retval = 0; - - ACT_LED_ON; - SET_DIR_READ(priv); - - dbg_printk(2, "board: %p lock %d length: %zu\n", - board, mutex_is_locked(&board->user_mutex), length); - - priv->end = 0; - priv->count = 0; - priv->rbuf = buffer; - if (length == 0) - goto read_end; - priv->request = length; - priv->eos_check = (priv->eos_flags & REOS) == 0; /* do eos check */ - priv->eos_check_8 = priv->eos_flags & BIN; /* over 8 bits */ - priv->eos_mask_7 = priv->eos & 0x7f; /* with this 7 bit eos */ - - dbg_printk(3, ".........." LINFMT "\n", LINVAL); - - spin_lock_irqsave(&priv->rw_lock, flags); - priv->dav_mode = 1; - priv->dav_rx = 1; - ENABLE_IRQ(priv->irq_DAV, IRQ_TYPE_LEVEL_LOW); - priv->end_flag = 0; - gpiod_set_value(NRFD, 1); // ready for data - priv->r_busy = 1; - priv->phase = 100; - spin_unlock_irqrestore(&priv->rw_lock, flags); - - /* wait for the interrupt routines finish their work */ - - retval = wait_event_interruptible(board->wait, - (priv->end_flag || board->status & TIMO)); - - dbg_printk(3, "awake from wait queue: %d\n", retval); - - if (retval == 0 && board->status & TIMO) { - retval = -ETIMEDOUT; - dbg_printk(1, "timeout\n"); - } else if (retval) { - retval = -ERESTARTSYS; - } - - DISABLE_IRQ(priv->irq_DAV); - spin_lock_irqsave(&priv->rw_lock, flags); - gpiod_set_value(NRFD, 0); // DIR_READ line state - priv->r_busy = 0; - spin_unlock_irqrestore(&priv->rw_lock, flags); - -read_end: - ACT_LED_OFF; - *bytes_read = priv->count; - *end = priv->end; - priv->r_busy = 0; - dbg_printk(2, "return: %d eoi|eos: %d count: %d\n\n", retval, priv->end, priv->count); - return retval; -} - -/*************************************************************************** - * * - * READ interrupt routine (DAV line) * - * * - ***************************************************************************/ - -static irqreturn_t bb_DAV_interrupt(int irq, void *arg) -{ - struct gpib_board *board = arg; - struct bb_priv *priv = board->private_data; - int val; - unsigned long flags; - - spin_lock_irqsave(&priv->rw_lock, flags); - - priv->all_irqs++; - - if (priv->dav_mode) { - ENABLE_IRQ(priv->irq_DAV, IRQ_TYPE_EDGE_BOTH); - priv->dav_mode = 0; - } - - if (priv->r_busy == 0) { - dbg_printk(1, "interrupt while idle after %d at %d\n", - priv->count, priv->phase); - priv->dav_idle++; - priv->phase = 200; - goto dav_exit; /* idle */ - } - - val = gpiod_get_value(DAV); - if (val == priv->dav_rx) { - dbg_printk(1, "out of order DAV interrupt %d/%d after %zu/%zu at %d cmd %d " - LINFMT ".\n", val, priv->dav_rx, priv->w_cnt, priv->length, - priv->phase, priv->cmd, LINVAL); - priv->dav_seq++; - } - priv->dav_rx = val; - - dbg_printk(3, "> irq: %d DAV: %d st: %4lx dir: %d busy: %d:%d\n", - irq, val, board->status, priv->direction, priv->r_busy, priv->w_busy); - - if (val == 0) { - gpiod_set_value(NRFD, 0); // not ready for data - priv->rbuf[priv->count++] = get_data_lines(); - priv->end = !gpiod_get_value(EOI); - gpiod_set_value(NDAC, 1); // data accepted - priv->end |= check_for_eos(priv, priv->rbuf[priv->count - 1]); - priv->end_flag = ((priv->count >= priv->request) || priv->end); - priv->phase = 210; - } else { - gpiod_set_value(NDAC, 0); // data not accepted - if (priv->end_flag) { - priv->r_busy = 0; - wake_up_interruptible(&board->wait); - priv->phase = 220; - } else { - gpiod_set_value(NRFD, 1); // ready for data - priv->phase = 230; - } - } - -dav_exit: - spin_unlock_irqrestore(&priv->rw_lock, flags); - dbg_printk(3, "< irq: %d count %d\n", irq, priv->count); - return IRQ_HANDLED; -} - -/*************************************************************************** - * * - * WRITE * - * * - ***************************************************************************/ - -static int bb_write(struct gpib_board *board, u8 *buffer, size_t length, - int send_eoi, size_t *bytes_written) -{ - unsigned long flags; - int retval = 0; - - struct bb_priv *priv = board->private_data; - - ACT_LED_ON; - - priv->w_cnt = 0; - priv->w_buf = buffer; - dbg_printk(2, "board %p lock %d length: %zu\n", - board, mutex_is_locked(&board->user_mutex), length); - - if (debug > 1) - bb_buffer_print(board, buffer, length, priv->cmd, send_eoi); - priv->count = 0; - priv->phase = 300; - - if (length == 0) - goto write_end; - priv->end = send_eoi; - priv->length = length; - - SET_DIR_WRITE(priv); - - dbg_printk(2, "Enabling interrupts - NRFD: %d NDAC: %d\n", - gpiod_get_value(NRFD), gpiod_get_value(NDAC)); - - if (gpiod_get_value(NRFD) && gpiod_get_value(NDAC)) { /* check for listener */ - retval = -ENOTCONN; - goto write_end; - } - - spin_lock_irqsave(&priv->rw_lock, flags); - priv->w_busy = 1; /* make the interrupt routines active */ - priv->write_done = 0; - priv->nrfd_mode = 1; - priv->ndac_mode = 1; - priv->dav_tx = 1; - ENABLE_IRQ(priv->irq_NDAC, IRQ_TYPE_LEVEL_HIGH); - ENABLE_IRQ(priv->irq_NRFD, IRQ_TYPE_LEVEL_HIGH); - spin_unlock_irqrestore(&priv->rw_lock, flags); - - /* wait for the interrupt routines finish their work */ - - retval = wait_event_interruptible(board->wait, - priv->write_done || (board->status & TIMO)); - - dbg_printk(3, "awake from wait queue: %d\n", retval); - - if (retval == 0) { - if (board->status & TIMO) { - retval = -ETIMEDOUT; - dbg_printk(1, "timeout after %zu/%zu at %d " LINFMT " eoi: %d\n", - priv->w_cnt, length, priv->phase, LINVAL, send_eoi); - } else { - retval = priv->w_cnt; - } - } else { - retval = -ERESTARTSYS; - } - - DISABLE_IRQ(priv->irq_NRFD); - DISABLE_IRQ(priv->irq_NDAC); - - spin_lock_irqsave(&priv->rw_lock, flags); - priv->w_busy = 0; - gpiod_set_value(DAV, 1); // DIR_WRITE line state - gpiod_set_value(EOI, 1); // De-assert EOI (in case) - spin_unlock_irqrestore(&priv->rw_lock, flags); - -write_end: - *bytes_written = priv->w_cnt; - ACT_LED_OFF; - dbg_printk(2, "sent %zu bytes\r\n\r\n", *bytes_written); - priv->phase = 310; - return retval; -} - -/*************************************************************************** - * * - * WRITE interrupt routine (NRFD line) * - * * - ***************************************************************************/ - -static irqreturn_t bb_NRFD_interrupt(int irq, void *arg) -{ - struct gpib_board *board = arg; - struct bb_priv *priv = board->private_data; - unsigned long flags; - int nrfd; - - spin_lock_irqsave(&priv->rw_lock, flags); - - nrfd = gpiod_get_value(NRFD); - priv->all_irqs++; - - dbg_printk(3, "> irq: %d NRFD: %d NDAC: %d st: %4lx dir: %d busy: %d:%d\n", - irq, nrfd, gpiod_get_value(NDAC), board->status, priv->direction, - priv->w_busy, priv->r_busy); - - if (priv->nrfd_mode) { - ENABLE_IRQ(priv->irq_NRFD, IRQ_TYPE_EDGE_RISING); - priv->nrfd_mode = 0; - } - - if (priv->w_busy == 0) { - dbg_printk(1, "interrupt while idle after %zu/%zu at %d\n", - priv->w_cnt, priv->length, priv->phase); - priv->nrfd_idle++; - goto nrfd_exit; /* idle */ - } - if (nrfd == 0) { - dbg_printk(1, "out of order interrupt after %zu/%zu at %d cmd %d " LINFMT ".\n", - priv->w_cnt, priv->length, priv->phase, priv->cmd, LINVAL); - priv->phase = 400; - priv->nrfd_seq++; - goto nrfd_exit; - } - if (!priv->dav_tx) { - dbg_printk(1, "DAV low after %zu/%zu cmd %d " LINFMT ". No action.\n", - priv->w_cnt, priv->length, priv->cmd, LINVAL); - priv->dav_seq++; - goto nrfd_exit; - } - - if (priv->w_cnt >= priv->length) { // test for missed NDAC end of transfer - dev_err(board->gpib_dev, "Unexpected NRFD exit\n"); - priv->write_done = 1; - priv->w_busy = 0; - wake_up_interruptible(&board->wait); - goto nrfd_exit; - } - - dbg_printk(3, "sending %zu\n", priv->w_cnt); - - set_data_lines(priv->w_buf[priv->w_cnt++]); // put the data on the lines - - if (priv->w_cnt == priv->length && priv->end) { - dbg_printk(3, "Asserting EOI\n"); - gpiod_set_value(EOI, 0); // Assert EOI - } - - gpiod_set_value(DAV, 0); // Data available - priv->dav_tx = 0; - priv->phase = 410; - -nrfd_exit: - spin_unlock_irqrestore(&priv->rw_lock, flags); - - return IRQ_HANDLED; -} - -/*************************************************************************** - * * - * WRITE interrupt routine (NDAC line) * - * * - ***************************************************************************/ - -static irqreturn_t bb_NDAC_interrupt(int irq, void *arg) -{ - struct gpib_board *board = arg; - struct bb_priv *priv = board->private_data; - unsigned long flags; - int ndac; - - spin_lock_irqsave(&priv->rw_lock, flags); - - ndac = gpiod_get_value(NDAC); - priv->all_irqs++; - dbg_printk(3, "> irq: %d NRFD: %d NDAC: %d st: %4lx dir: %d busy: %d:%d\n", - irq, gpiod_get_value(NRFD), ndac, board->status, priv->direction, - priv->w_busy, priv->r_busy); - - if (priv->ndac_mode) { - ENABLE_IRQ(priv->irq_NDAC, IRQ_TYPE_EDGE_RISING); - priv->ndac_mode = 0; - } - - if (priv->w_busy == 0) { - dbg_printk(1, "interrupt while idle.\n"); - priv->ndac_idle++; - goto ndac_exit; - } - if (ndac == 0) { - dbg_printk(1, "out of order interrupt at %zu:%d.\n", priv->w_cnt, priv->phase); - priv->phase = 500; - priv->ndac_seq++; - goto ndac_exit; - } - if (priv->dav_tx) { - dbg_printk(1, "DAV high after %zu/%zu cmd %d " LINFMT ". No action.\n", - priv->w_cnt, priv->length, priv->cmd, LINVAL); - priv->dav_seq++; - goto ndac_exit; - } - - dbg_printk(3, "accepted %zu\n", priv->w_cnt - 1); - - gpiod_set_value(DAV, 1); // Data not available - priv->dav_tx = 1; - priv->phase = 510; - - if (priv->w_cnt >= priv->length) { // test for end of transfer - priv->write_done = 1; - priv->w_busy = 0; - wake_up_interruptible(&board->wait); - } - -ndac_exit: - spin_unlock_irqrestore(&priv->rw_lock, flags); - return IRQ_HANDLED; -} - -/*************************************************************************** - * * - * interrupt routine for SRQ line * - * * - ***************************************************************************/ - -static irqreturn_t bb_SRQ_interrupt(int irq, void *arg) -{ - struct gpib_board *board = arg; - - int val = gpiod_get_value(SRQ); - - dbg_printk(3, "> %d st: %4lx\n", val, board->status); - - if (!val) - set_bit(SRQI_NUM, &board->status); /* set_bit() is atomic */ - - wake_up_interruptible(&board->wait); - - return IRQ_HANDLED; -} - -static int bb_command(struct gpib_board *board, u8 *buffer, - size_t length, size_t *bytes_written) -{ - int ret; - struct bb_priv *priv = board->private_data; - int i; - - dbg_printk(2, "%p %p\n", buffer, board->buffer); - - /* the _ATN line has already been asserted by bb_take_control() */ - - priv->cmd = 1; - - ret = bb_write(board, buffer, length, 0, bytes_written); // no eoi - - for (i = 0; i < length; i++) { - if (buffer[i] == UNT) { - priv->talker_state = talker_idle; - } else { - if (buffer[i] == UNL) { - priv->listener_state = listener_idle; - } else { - if (buffer[i] == (MTA(board->pad))) { - priv->talker_state = talker_addressed; - priv->listener_state = listener_idle; - } else if (buffer[i] == (MLA(board->pad))) { - priv->listener_state = listener_addressed; - priv->talker_state = talker_idle; - } - } - } - } - - /* the _ATN line will be released by bb_go_to_stby */ - - priv->cmd = 0; - - return ret; -} - -/*************************************************************************** - * * - * Buffer print with decode for debug/trace * - * * - ***************************************************************************/ - -static char *cmd_string[32] = { - "", // 0x00 - "GTL", // 0x01 - "", // 0x02 - "", // 0x03 - "SDC", // 0x04 - "PPC", // 0x05 - "", // 0x06 - "", // 0x07 - "GET", // 0x08 - "TCT", // 0x09 - "", // 0x0a - "", // 0x0b - "", // 0x0c - "", // 0x0d - "", // 0x0e - "", // 0x0f - "", // 0x10 - "LLO", // 0x11 - "", // 0x12 - "", // 0x13 - "DCL", // 0x14 - "PPU", // 0x15 - "", // 0x16 - "", // 0x17 - "SPE", // 0x18 - "SPD", // 0x19 - "", // 0x1a - "", // 0x1b - "", // 0x1c - "", // 0x1d - "", // 0x1e - "CFE" // 0x1f -}; - -static void bb_buffer_print(struct gpib_board *board, unsigned char *buffer, size_t length, - int cmd, int eoi) -{ - int i; - - if (cmd) { - dbg_printk(2, "<cmd len %zu>\n", length); - for (i = 0; i < length; i++) { - if (buffer[i] < 0x20) { - dbg_printk(3, "0x%x=%s\n", buffer[i], cmd_string[buffer[i]]); - } else if (buffer[i] == 0x3f) { - dbg_printk(3, "0x%x=%s\n", buffer[i], "UNL"); - } else if (buffer[i] == 0x5f) { - dbg_printk(3, "0x%x=%s\n", buffer[i], "UNT"); - } else if (buffer[i] < 0x60) { - dbg_printk(3, "0x%x=%s%d\n", buffer[i], - (buffer[i] & 0x40) ? "TLK" : "LSN", buffer[i] & 0x1F); - } else { - dbg_printk(3, "0x%x\n", buffer[i]); - } - } - } else { - dbg_printk(2, "<data len %zu %s>\n", length, (eoi) ? "w.EOI" : " "); - for (i = 0; i < length; i++) - dbg_printk(2, "%3d 0x%x->%c\n", i, buffer[i], printable(buffer[i])); - } -} - -/*************************************************************************** - * * - * STATUS Management * - * * - ***************************************************************************/ -static void set_atn(struct gpib_board *board, int atn_asserted) -{ - struct bb_priv *priv = board->private_data; - - if (priv->listener_state != listener_idle && - priv->talker_state != talker_idle) { - dev_err(board->gpib_dev, "listener/talker state machine conflict\n"); - } - if (atn_asserted) { - if (priv->listener_state == listener_active) - priv->listener_state = listener_addressed; - if (priv->talker_state == talker_active) - priv->talker_state = talker_addressed; - SET_DIR_WRITE(priv); // need to be able to read bus NRFD/NDAC - } else { - if (priv->listener_state == listener_addressed) { - priv->listener_state = listener_active; - SET_DIR_READ(priv); // make sure holdoff is active when we unassert ATN - } - if (priv->talker_state == talker_addressed) - priv->talker_state = talker_active; - } - gpiod_direction_output(_ATN, !atn_asserted); -} - -static int bb_take_control(struct gpib_board *board, int synchronous) -{ - dbg_printk(2, "%d\n", synchronous); - set_atn(board, 1); - return 0; -} - -static int bb_go_to_standby(struct gpib_board *board) -{ - dbg_printk(2, "\n"); - set_atn(board, 0); - return 0; -} - -static int bb_request_system_control(struct gpib_board *board, int request_control) -{ - struct bb_priv *priv = board->private_data; - - dbg_printk(2, "%d\n", request_control); - if (!request_control) - return -EINVAL; - - gpiod_direction_output(REN, 1); /* user space must enable REN if needed */ - gpiod_direction_output(IFC, 1); /* user space must toggle IFC if needed */ - if (sn7516x) - gpiod_direction_output(DC, 0); /* enable ATN as output on SN75161/2 */ - - gpiod_direction_input(SRQ); - - ENABLE_IRQ(priv->irq_SRQ, IRQ_TYPE_EDGE_FALLING); - - return 0; -} - -static void bb_interface_clear(struct gpib_board *board, int assert) -{ - struct bb_priv *priv = board->private_data; - - dbg_printk(2, "%d\n", assert); - if (assert) { - gpiod_direction_output(IFC, 0); - priv->talker_state = talker_idle; - priv->listener_state = listener_idle; - set_bit(CIC_NUM, &board->status); - } else { - gpiod_direction_output(IFC, 1); - } -} - -static void bb_remote_enable(struct gpib_board *board, int enable) -{ - dbg_printk(2, "%d\n", enable); - if (enable) { - set_bit(REM_NUM, &board->status); - gpiod_direction_output(REN, 0); - } else { - clear_bit(REM_NUM, &board->status); - gpiod_direction_output(REN, 1); - } -} - -static int bb_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits) -{ - struct bb_priv *priv = board->private_data; - - dbg_printk(2, "%s\n", "EOS_en"); - priv->eos = eos_byte; - priv->eos_flags = REOS; - if (compare_8_bits) - priv->eos_flags |= BIN; - - return 0; -} - -static void bb_disable_eos(struct gpib_board *board) -{ - struct bb_priv *priv = board->private_data; - - dbg_printk(2, "\n"); - priv->eos_flags &= ~REOS; -} - -static unsigned int bb_update_status(struct gpib_board *board, unsigned int clear_mask) -{ - struct bb_priv *priv = board->private_data; - - board->status &= ~clear_mask; - - if (gpiod_get_value(SRQ)) /* SRQ asserted low */ - clear_bit(SRQI_NUM, &board->status); - else - set_bit(SRQI_NUM, &board->status); - if (gpiod_get_value(_ATN)) /* ATN asserted low */ - clear_bit(ATN_NUM, &board->status); - else - set_bit(ATN_NUM, &board->status); - if (priv->talker_state == talker_active || - priv->talker_state == talker_addressed) - set_bit(TACS_NUM, &board->status); - else - clear_bit(TACS_NUM, &board->status); - - if (priv->listener_state == listener_active || - priv->listener_state == listener_addressed) - set_bit(LACS_NUM, &board->status); - else - clear_bit(LACS_NUM, &board->status); - - dbg_printk(2, "0x%lx mask 0x%x\n", board->status, clear_mask); - - return board->status; -} - -static int bb_primary_address(struct gpib_board *board, unsigned int address) -{ - dbg_printk(2, "%d\n", address); - board->pad = address; - return 0; -} - -static int bb_secondary_address(struct gpib_board *board, unsigned int address, int enable) -{ - dbg_printk(2, "%d %d\n", address, enable); - if (enable) - board->sad = address; - return 0; -} - -static int bb_parallel_poll(struct gpib_board *board, u8 *result) -{ - return -ENOENT; -} - -static void bb_parallel_poll_configure(struct gpib_board *board, u8 config) -{ -} - -static void bb_parallel_poll_response(struct gpib_board *board, int ist) -{ -} - -static void bb_serial_poll_response(struct gpib_board *board, u8 status) -{ -} - -static u8 bb_serial_poll_status(struct gpib_board *board) -{ - return 0; // -ENOENT; -} - -static int bb_t1_delay(struct gpib_board *board, unsigned int nano_sec) -{ - struct bb_priv *priv = board->private_data; - - if (nano_sec <= 350) - priv->t1_delay = 350; - else if (nano_sec <= 1100) - priv->t1_delay = 1100; - else - priv->t1_delay = 2000; - - dbg_printk(2, "t1 delay set to %d nanosec\n", priv->t1_delay); - - return priv->t1_delay; -} - -static void bb_return_to_local(struct gpib_board *board) -{ -} - -static int bb_line_status(const struct gpib_board *board) -{ - int line_status = VALID_ALL; - - if (gpiod_get_value(REN) == 0) - line_status |= BUS_REN; - if (gpiod_get_value(IFC) == 0) - line_status |= BUS_IFC; - if (gpiod_get_value(NDAC) == 0) - line_status |= BUS_NDAC; - if (gpiod_get_value(NRFD) == 0) - line_status |= BUS_NRFD; - if (gpiod_get_value(DAV) == 0) - line_status |= BUS_DAV; - if (gpiod_get_value(EOI) == 0) - line_status |= BUS_EOI; - if (gpiod_get_value(_ATN) == 0) - line_status |= BUS_ATN; - if (gpiod_get_value(SRQ) == 0) - line_status |= BUS_SRQ; - - dbg_printk(2, "status lines: %4x\n", line_status); - - return line_status; -} - -/*************************************************************************** - * * - * Module Management * - * * - ***************************************************************************/ - -static int allocate_private(struct gpib_board *board) -{ - board->private_data = kzalloc(sizeof(struct bb_priv), GFP_KERNEL); - if (!board->private_data) - return -1; - return 0; -} - -static void free_private(struct gpib_board *board) -{ - kfree(board->private_data); - board->private_data = NULL; -} - -static int bb_get_irq(struct gpib_board *board, char *name, - struct gpio_desc *gpio, int *irq, - irq_handler_t handler, irq_handler_t thread_fn, unsigned long flags) -{ - if (!gpio) - return -1; - gpiod_direction_input(gpio); - *irq = gpiod_to_irq(gpio); - dbg_printk(2, "IRQ %s: %d\n", name, *irq); - if (*irq < 0) { - dev_err(board->gpib_dev, "can't get IRQ for %s\n", name); - return -1; - } - if (request_threaded_irq(*irq, handler, thread_fn, flags, name, board)) { - dev_err(board->gpib_dev, "can't request IRQ for %s %d\n", name, *irq); - *irq = 0; - return -1; - } - DISABLE_IRQ(*irq); - return 0; -} - -static void bb_free_irq(struct gpib_board *board, int *irq, char *name) -{ - if (*irq) { - free_irq(*irq, board); - dbg_printk(2, "IRQ %d(%s) freed\n", *irq, name); - *irq = 0; - } -} - -static void release_gpios(void) -{ - int j; - - for (j = 0 ; j < NUM_PINS ; j++) { - if (all_descriptors[j]) { - gpiod_put(all_descriptors[j]); - all_descriptors[j] = NULL; - } - } -} - -static int allocate_gpios(struct gpib_board *board) -{ - int j; - int table_index = 0; - char name[256]; - struct gpio_desc *desc; - struct gpiod_lookup_table *lookup_table; - - if (!board->gpib_dev) { - pr_err("NULL gpib dev for board\n"); - return -ENOENT; - } - - lookup_table = lookup_tables[table_index]; - lookup_table->dev_id = dev_name(board->gpib_dev); - gpiod_add_lookup_table(lookup_table); - dbg_printk(1, "Allocating gpios using table index %d\n", table_index); - - for (j = 0 ; j < NUM_PINS ; j++) { - if (gpios_vector[j] < 0) - continue; - /* name not really used in gpiod_get_index() */ - sprintf(name, "GPIO%d", gpios_vector[j]); -try_again: - dbg_printk(1, "Allocating gpio %s pin no %d\n", name, gpios_vector[j]); - desc = gpiod_get_index(board->gpib_dev, name, gpios_vector[j], GPIOD_IN); - - if (IS_ERR(desc)) { - gpiod_remove_lookup_table(lookup_table); - table_index++; - lookup_table = lookup_tables[table_index]; - if (!lookup_table) { - dev_err(board->gpib_dev, "Unable to obtain gpio descriptor for pin %d error %ld\n", - gpios_vector[j], PTR_ERR(desc)); - goto alloc_gpios_fail; - } - dbg_printk(1, "Allocation failed, now using table_index %d\n", table_index); - lookup_table->dev_id = dev_name(board->gpib_dev); - gpiod_add_lookup_table(lookup_table); - goto try_again; - } - all_descriptors[j] = desc; - } - - gpiod_remove_lookup_table(lookup_table); - - return 0; - -alloc_gpios_fail: - release_gpios(); - return -1; -} - -static void bb_detach(struct gpib_board *board) -{ - struct bb_priv *priv = board->private_data; - - dbg_printk(2, "Enter with data %p\n", board->private_data); - if (!board->private_data) - return; - - bb_free_irq(board, &priv->irq_DAV, NAME "_DAV"); - bb_free_irq(board, &priv->irq_NRFD, NAME "_NRFD"); - bb_free_irq(board, &priv->irq_NDAC, NAME "_NDAC"); - bb_free_irq(board, &priv->irq_SRQ, NAME "_SRQ"); - - if (strcmp(PINMAP_2, pin_map) == 0) { /* YOGA */ - gpiod_set_value(YOGA_ENABLE, 0); - } - - release_gpios(); - - dbg_printk(2, "detached board: %d\n", board->minor); - dbg_printk(0, "NRFD: idle %d, seq %d, NDAC: idle %d, seq %d DAV: idle %d seq: %d all: %ld", - priv->nrfd_idle, priv->nrfd_seq, - priv->ndac_idle, priv->ndac_seq, - priv->dav_idle, priv->dav_seq, priv->all_irqs); - - free_private(board); -} - -static int bb_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct bb_priv *priv; - int retval = 0; - - dbg_printk(2, "%s\n", "Enter ..."); - - board->status = 0; - - if (allocate_private(board)) - return -ENOMEM; - priv = board->private_data; - priv->direction = -1; - priv->t1_delay = 2000; - priv->listener_state = listener_idle; - priv->talker_state = talker_idle; - - sn7516x = sn7516x_used; - if (strcmp(PINMAP_0, pin_map) == 0) { - if (!sn7516x) { - gpios_vector[&(PE) - &all_descriptors[0]] = -1; - gpios_vector[&(DC) - &all_descriptors[0]] = -1; - gpios_vector[&(TE) - &all_descriptors[0]] = -1; - } - } else if (strcmp(PINMAP_1, pin_map) == 0) { - if (!sn7516x) { - gpios_vector[&(PE) - &all_descriptors[0]] = -1; - gpios_vector[&(DC) - &all_descriptors[0]] = -1; - gpios_vector[&(TE) - &all_descriptors[0]] = -1; - } - gpios_vector[&(REN) - &all_descriptors[0]] = 0; /* 27 -> 0 REN on GPIB pin 0 */ - } else if (strcmp(PINMAP_2, pin_map) == 0) { /* YOGA */ - sn7516x = 0; - gpios_vector[&(D03) - &all_descriptors[0]] = YOGA_D03_pin_nr; - gpios_vector[&(D04) - &all_descriptors[0]] = YOGA_D04_pin_nr; - gpios_vector[&(D05) - &all_descriptors[0]] = YOGA_D05_pin_nr; - gpios_vector[&(D06) - &all_descriptors[0]] = YOGA_D06_pin_nr; - gpios_vector[&(PE) - &all_descriptors[0]] = -1; - gpios_vector[&(DC) - &all_descriptors[0]] = -1; - } else { - dev_err(board->gpib_dev, "Unrecognized pin map %s\n", pin_map); - goto bb_attach_fail; - } - dbg_printk(0, "Using pin map \"%s\" %s\n", pin_map, (sn7516x) ? - " with SN7516x driver support" : ""); - - if (allocate_gpios(board)) - goto bb_attach_fail; - -/* - * Configure SN7516X control lines. - * drive ATN, IFC and REN as outputs only when master - * i.e. system controller. In this mode can only be the CIC - * When not master then enable device mode ATN, IFC & REN as inputs - */ - if (sn7516x) { - gpiod_direction_output(DC, 0); - gpiod_direction_output(TE, 1); - gpiod_direction_output(PE, 1); - } -/* Set main control lines to a known state */ - gpiod_direction_output(IFC, 1); - gpiod_direction_output(REN, 1); - gpiod_direction_output(_ATN, 1); - - if (strcmp(PINMAP_2, pin_map) == 0) { /* YOGA: enable level shifters */ - gpiod_direction_output(YOGA_ENABLE, 1); - } - - spin_lock_init(&priv->rw_lock); - - /* request DAV interrupt for read */ - if (bb_get_irq(board, NAME "_DAV", DAV, &priv->irq_DAV, bb_DAV_interrupt, NULL, - IRQF_TRIGGER_NONE)) - goto bb_attach_fail_r; - - /* request NRFD interrupt for write */ - if (bb_get_irq(board, NAME "_NRFD", NRFD, &priv->irq_NRFD, bb_NRFD_interrupt, NULL, - IRQF_TRIGGER_NONE)) - goto bb_attach_fail_r; - - /* request NDAC interrupt for write */ - if (bb_get_irq(board, NAME "_NDAC", NDAC, &priv->irq_NDAC, bb_NDAC_interrupt, NULL, - IRQF_TRIGGER_NONE)) - goto bb_attach_fail_r; - - /* request SRQ interrupt for Service Request */ - if (bb_get_irq(board, NAME "_SRQ", SRQ, &priv->irq_SRQ, bb_SRQ_interrupt, NULL, - IRQF_TRIGGER_NONE)) - goto bb_attach_fail_r; - - dbg_printk(0, "attached board %d\n", board->minor); - goto bb_attach_out; - -bb_attach_fail_r: - release_gpios(); -bb_attach_fail: - retval = -1; -bb_attach_out: - return retval; -} - -static struct gpib_interface bb_interface = { - .name = NAME, - .attach = bb_attach, - .detach = bb_detach, - .read = bb_read, - .write = bb_write, - .command = bb_command, - .take_control = bb_take_control, - .go_to_standby = bb_go_to_standby, - .request_system_control = bb_request_system_control, - .interface_clear = bb_interface_clear, - .remote_enable = bb_remote_enable, - .enable_eos = bb_enable_eos, - .disable_eos = bb_disable_eos, - .parallel_poll = bb_parallel_poll, - .parallel_poll_configure = bb_parallel_poll_configure, - .parallel_poll_response = bb_parallel_poll_response, - .line_status = bb_line_status, - .update_status = bb_update_status, - .primary_address = bb_primary_address, - .secondary_address = bb_secondary_address, - .serial_poll_response = bb_serial_poll_response, - .serial_poll_status = bb_serial_poll_status, - .t1_delay = bb_t1_delay, - .return_to_local = bb_return_to_local, -}; - -static int __init bb_init_module(void) -{ - int result = gpib_register_driver(&bb_interface, THIS_MODULE); - - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - return result; - } - - return 0; -} - -static void __exit bb_exit_module(void) -{ - gpib_unregister_driver(&bb_interface); -} - -module_init(bb_init_module); -module_exit(bb_exit_module); - -/*************************************************************************** - * * - * UTILITY Functions * - * * - ***************************************************************************/ -inline long usec_diff(struct timespec64 *a, struct timespec64 *b) -{ - return ((a->tv_sec - b->tv_sec) * 1000000 + - (a->tv_nsec - b->tv_nsec) / 1000); -} - -static inline int check_for_eos(struct bb_priv *priv, u8 byte) -{ - if (priv->eos_check) - return 0; - - if (priv->eos_check_8) { - if (priv->eos == byte) - return 1; - } else { - if (priv->eos_mask_7 == (byte & 0x7f)) - return 1; - } - return 0; -} - -static void set_data_lines_output(void) -{ - gpiod_direction_output(D01, 1); - gpiod_direction_output(D02, 1); - gpiod_direction_output(D03, 1); - gpiod_direction_output(D04, 1); - gpiod_direction_output(D05, 1); - gpiod_direction_output(D06, 1); - gpiod_direction_output(D07, 1); - gpiod_direction_output(D08, 1); -} - -static void set_data_lines(u8 byte) -{ - gpiod_set_value(D01, !(byte & 0x01)); - gpiod_set_value(D02, !(byte & 0x02)); - gpiod_set_value(D03, !(byte & 0x04)); - gpiod_set_value(D04, !(byte & 0x08)); - gpiod_set_value(D05, !(byte & 0x10)); - gpiod_set_value(D06, !(byte & 0x20)); - gpiod_set_value(D07, !(byte & 0x40)); - gpiod_set_value(D08, !(byte & 0x80)); -} - -static u8 get_data_lines(void) -{ - u8 ret; - - ret = gpiod_get_value(D01); - ret |= gpiod_get_value(D02) << 1; - ret |= gpiod_get_value(D03) << 2; - ret |= gpiod_get_value(D04) << 3; - ret |= gpiod_get_value(D05) << 4; - ret |= gpiod_get_value(D06) << 5; - ret |= gpiod_get_value(D07) << 6; - ret |= gpiod_get_value(D08) << 7; - return ~ret; -} - -static void set_data_lines_input(void) -{ - gpiod_direction_input(D01); - gpiod_direction_input(D02); - gpiod_direction_input(D03); - gpiod_direction_input(D04); - gpiod_direction_input(D05); - gpiod_direction_input(D06); - gpiod_direction_input(D07); - gpiod_direction_input(D08); -} - -static inline void SET_DIR_WRITE(struct bb_priv *priv) -{ - if (priv->direction == DIR_WRITE) - return; - - gpiod_direction_input(NRFD); - gpiod_direction_input(NDAC); - set_data_lines_output(); - gpiod_direction_output(DAV, 1); - gpiod_direction_output(EOI, 1); - - if (sn7516x) { - gpiod_set_value(PE, 1); /* set data lines to transmit on sn75160b */ - gpiod_set_value(TE, 1); /* set NDAC and NRFD to receive and DAV to transmit */ - } - - priv->direction = DIR_WRITE; -} - -static inline void SET_DIR_READ(struct bb_priv *priv) -{ - if (priv->direction == DIR_READ) - return; - - gpiod_direction_input(DAV); - gpiod_direction_input(EOI); - - set_data_lines_input(); - - if (sn7516x) { - gpiod_set_value(PE, 0); /* set data lines to receive on sn75160b */ - gpiod_set_value(TE, 0); /* set NDAC and NRFD to transmit and DAV to receive */ - } - - gpiod_direction_output(NRFD, 0); /* hold off the talker */ - gpiod_direction_output(NDAC, 0); /* data not accepted */ - - priv->direction = DIR_READ; -} diff --git a/drivers/staging/gpib/hp_82335/Makefile b/drivers/staging/gpib/hp_82335/Makefile deleted file mode 100644 index 305ce44ee48a..000000000000 --- a/drivers/staging/gpib/hp_82335/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -obj-$(CONFIG_GPIB_HP82335) += hp82335.o - - diff --git a/drivers/staging/gpib/hp_82335/hp82335.c b/drivers/staging/gpib/hp_82335/hp82335.c deleted file mode 100644 index d0e47ef77c87..000000000000 --- a/drivers/staging/gpib/hp_82335/hp82335.c +++ /dev/null @@ -1,371 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * copyright : (C) 2002 by Frank Mori Hess * - ***************************************************************************/ - -/* - * should enable ATN interrupts (and update board->status on occurrence), - * implement recovery from bus errors (if necessary) - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define DRV_NAME KBUILD_MODNAME - -#include "hp82335.h" -#include <linux/io.h> -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/init.h> - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB driver for HP 82335 interface cards"); - -static int hp82335_attach(struct gpib_board *board, const struct gpib_board_config *config); -static void hp82335_detach(struct gpib_board *board); -static irqreturn_t hp82335_interrupt(int irq, void *arg); - -// wrappers for interface functions -static int hp82335_read(struct gpib_board *board, u8 *buffer, size_t length, - int *end, size_t *bytes_read) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read); -} - -static int hp82335_write(struct gpib_board *board, u8 *buffer, size_t length, int send_eoi, - size_t *bytes_written) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written); -} - -static int hp82335_command(struct gpib_board *board, u8 *buffer, size_t length, - size_t *bytes_written) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written); -} - -static int hp82335_take_control(struct gpib_board *board, int synchronous) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_take_control(board, &priv->tms9914_priv, synchronous); -} - -static int hp82335_go_to_standby(struct gpib_board *board) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_go_to_standby(board, &priv->tms9914_priv); -} - -static int hp82335_request_system_control(struct gpib_board *board, int request_control) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_request_system_control(board, &priv->tms9914_priv, request_control); -} - -static void hp82335_interface_clear(struct gpib_board *board, int assert) -{ - struct hp82335_priv *priv = board->private_data; - - tms9914_interface_clear(board, &priv->tms9914_priv, assert); -} - -static void hp82335_remote_enable(struct gpib_board *board, int enable) -{ - struct hp82335_priv *priv = board->private_data; - - tms9914_remote_enable(board, &priv->tms9914_priv, enable); -} - -static int hp82335_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits); -} - -static void hp82335_disable_eos(struct gpib_board *board) -{ - struct hp82335_priv *priv = board->private_data; - - tms9914_disable_eos(board, &priv->tms9914_priv); -} - -static unsigned int hp82335_update_status(struct gpib_board *board, unsigned int clear_mask) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_update_status(board, &priv->tms9914_priv, clear_mask); -} - -static int hp82335_primary_address(struct gpib_board *board, unsigned int address) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_primary_address(board, &priv->tms9914_priv, address); -} - -static int hp82335_secondary_address(struct gpib_board *board, unsigned int address, int enable) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable); -} - -static int hp82335_parallel_poll(struct gpib_board *board, u8 *result) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_parallel_poll(board, &priv->tms9914_priv, result); -} - -static void hp82335_parallel_poll_configure(struct gpib_board *board, u8 config) -{ - struct hp82335_priv *priv = board->private_data; - - tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config); -} - -static void hp82335_parallel_poll_response(struct gpib_board *board, int ist) -{ - struct hp82335_priv *priv = board->private_data; - - tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist); -} - -static void hp82335_serial_poll_response(struct gpib_board *board, u8 status) -{ - struct hp82335_priv *priv = board->private_data; - - tms9914_serial_poll_response(board, &priv->tms9914_priv, status); -} - -static u8 hp82335_serial_poll_status(struct gpib_board *board) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_serial_poll_status(board, &priv->tms9914_priv); -} - -static int hp82335_line_status(const struct gpib_board *board) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_line_status(board, &priv->tms9914_priv); -} - -static int hp82335_t1_delay(struct gpib_board *board, unsigned int nano_sec) -{ - struct hp82335_priv *priv = board->private_data; - - return tms9914_t1_delay(board, &priv->tms9914_priv, nano_sec); -} - -static void hp82335_return_to_local(struct gpib_board *board) -{ - struct hp82335_priv *priv = board->private_data; - - tms9914_return_to_local(board, &priv->tms9914_priv); -} - -static struct gpib_interface hp82335_interface = { - .name = "hp82335", - .attach = hp82335_attach, - .detach = hp82335_detach, - .read = hp82335_read, - .write = hp82335_write, - .command = hp82335_command, - .request_system_control = hp82335_request_system_control, - .take_control = hp82335_take_control, - .go_to_standby = hp82335_go_to_standby, - .interface_clear = hp82335_interface_clear, - .remote_enable = hp82335_remote_enable, - .enable_eos = hp82335_enable_eos, - .disable_eos = hp82335_disable_eos, - .parallel_poll = hp82335_parallel_poll, - .parallel_poll_configure = hp82335_parallel_poll_configure, - .parallel_poll_response = hp82335_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = hp82335_line_status, - .update_status = hp82335_update_status, - .primary_address = hp82335_primary_address, - .secondary_address = hp82335_secondary_address, - .serial_poll_response = hp82335_serial_poll_response, - .serial_poll_status = hp82335_serial_poll_status, - .t1_delay = hp82335_t1_delay, - .return_to_local = hp82335_return_to_local, -}; - -static int hp82335_allocate_private(struct gpib_board *board) -{ - board->private_data = kzalloc(sizeof(struct hp82335_priv), GFP_KERNEL); - if (!board->private_data) - return -1; - return 0; -} - -static void hp82335_free_private(struct gpib_board *board) -{ - kfree(board->private_data); - board->private_data = NULL; -} - -static inline unsigned int tms9914_to_hp82335_offset(unsigned int register_num) -{ - return 0x1ff8 + register_num; -} - -static u8 hp82335_read_byte(struct tms9914_priv *priv, unsigned int register_num) -{ - return tms9914_iomem_read_byte(priv, tms9914_to_hp82335_offset(register_num)); -} - -static void hp82335_write_byte(struct tms9914_priv *priv, u8 data, unsigned int register_num) -{ - tms9914_iomem_write_byte(priv, data, tms9914_to_hp82335_offset(register_num)); -} - -static void hp82335_clear_interrupt(struct hp82335_priv *hp_priv) -{ - struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; - - writeb(0, tms_priv->mmiobase + HPREG_INTR_CLEAR); -} - -static int hp82335_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct hp82335_priv *hp_priv; - struct tms9914_priv *tms_priv; - int retval; - const unsigned long upper_iomem_base = config->ibbase + hp82335_rom_size; - - board->status = 0; - - if (hp82335_allocate_private(board)) - return -ENOMEM; - hp_priv = board->private_data; - tms_priv = &hp_priv->tms9914_priv; - tms_priv->read_byte = hp82335_read_byte; - tms_priv->write_byte = hp82335_write_byte; - tms_priv->offset = 1; - - switch (config->ibbase) { - case 0xc4000: - case 0xc8000: - case 0xcc000: - case 0xd0000: - case 0xd4000: - case 0xd8000: - case 0xdc000: - case 0xe0000: - case 0xe4000: - case 0xe8000: - case 0xec000: - case 0xf0000: - case 0xf4000: - case 0xf8000: - case 0xfc000: - break; - default: - dev_err(board->gpib_dev, "invalid base io address 0x%x\n", config->ibbase); - return -EINVAL; - } - if (!request_mem_region(upper_iomem_base, hp82335_upper_iomem_size, "hp82335")) { - dev_err(board->gpib_dev, "failed to allocate io memory region 0x%lx-0x%lx\n", - upper_iomem_base, upper_iomem_base + hp82335_upper_iomem_size - 1); - return -EBUSY; - } - hp_priv->raw_iobase = upper_iomem_base; - tms_priv->mmiobase = ioremap(upper_iomem_base, hp82335_upper_iomem_size); - - retval = request_irq(config->ibirq, hp82335_interrupt, 0, DRV_NAME, board); - if (retval) { - dev_err(board->gpib_dev, "can't request IRQ %d\n", config->ibirq); - return retval; - } - hp_priv->irq = config->ibirq; - - tms9914_board_reset(tms_priv); - - hp82335_clear_interrupt(hp_priv); - - writeb(INTR_ENABLE, tms_priv->mmiobase + HPREG_CCR); - - tms9914_online(board, tms_priv); - - return 0; -} - -static void hp82335_detach(struct gpib_board *board) -{ - struct hp82335_priv *hp_priv = board->private_data; - struct tms9914_priv *tms_priv; - - if (hp_priv) { - tms_priv = &hp_priv->tms9914_priv; - if (hp_priv->irq) - free_irq(hp_priv->irq, board); - if (tms_priv->mmiobase) { - writeb(0, tms_priv->mmiobase + HPREG_CCR); - tms9914_board_reset(tms_priv); - iounmap(tms_priv->mmiobase); - } - if (hp_priv->raw_iobase) - release_mem_region(hp_priv->raw_iobase, hp82335_upper_iomem_size); - } - hp82335_free_private(board); -} - -static int __init hp82335_init_module(void) -{ - int result = gpib_register_driver(&hp82335_interface, THIS_MODULE); - - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - return result; - } - - return 0; -} - -static void __exit hp82335_exit_module(void) -{ - gpib_unregister_driver(&hp82335_interface); -} - -module_init(hp82335_init_module); -module_exit(hp82335_exit_module); - -/* - * GPIB interrupt service routines - */ - -static irqreturn_t hp82335_interrupt(int irq, void *arg) -{ - int status1, status2; - struct gpib_board *board = arg; - struct hp82335_priv *priv = board->private_data; - unsigned long flags; - irqreturn_t retval; - - spin_lock_irqsave(&board->spinlock, flags); - status1 = read_byte(&priv->tms9914_priv, ISR0); - status2 = read_byte(&priv->tms9914_priv, ISR1); - hp82335_clear_interrupt(priv); - retval = tms9914_interrupt_have_status(board, &priv->tms9914_priv, status1, status2); - spin_unlock_irqrestore(&board->spinlock, flags); - return retval; -} - diff --git a/drivers/staging/gpib/hp_82335/hp82335.h b/drivers/staging/gpib/hp_82335/hp82335.h deleted file mode 100644 index 0c252a712ec9..000000000000 --- a/drivers/staging/gpib/hp_82335/hp82335.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002 by Frank Mori Hess * - ***************************************************************************/ - -#ifndef _HP82335_H -#define _HP82335_H - -#include "tms9914.h" -#include "gpibP.h" - -// struct which defines private_data for board -struct hp82335_priv { - struct tms9914_priv tms9914_priv; - unsigned int irq; - unsigned long raw_iobase; -}; - -// size of io memory region used -static const int hp82335_rom_size = 0x2000; -static const int hp82335_upper_iomem_size = 0x2000; - -// hp82335 register offsets -enum hp_read_regs { - HPREG_CSR = 0x17f8, - HPREG_STATUS = 0x1ffc, -}; - -enum hp_write_regs { - HPREG_INTR_CLEAR = 0x17f7, - HPREG_CCR = HPREG_CSR, -}; - -enum ccr_bits { - DMA_ENABLE = (1 << 0), /* DMA enable */ - DMA_CHAN_SELECT = (1 << 1), /* DMA channel select O=3,1=2 */ - INTR_ENABLE = (1 << 2), /* interrupt enable */ - SYS_DISABLE = (1 << 3), /* system controller disable */ -}; - -enum csr_bits { - SWITCH6 = (1 << 0), /* switch 6 position */ - SWITCH5 = (1 << 1), /* switch 5 position */ - SYS_CONTROLLER = (1 << 2), /* system controller bit */ - DMA_ENABLE_STATUS = (1 << 4), /* DMA enabled */ - DMA_CHAN_STATUS = (1 << 5), /* DMA channel 0=3,1=2 */ - INTR_ENABLE_STATUS = (1 << 6), /* Interrupt enable */ - INTR_PENDING = (1 << 7), /* Interrupt Pending */ -}; - -#endif // _HP82335_H diff --git a/drivers/staging/gpib/hp_82341/Makefile b/drivers/staging/gpib/hp_82341/Makefile deleted file mode 100644 index 21367310a17e..000000000000 --- a/drivers/staging/gpib/hp_82341/Makefile +++ /dev/null @@ -1,2 +0,0 @@ - -obj-$(CONFIG_GPIB_HP82341) += hp_82341.o diff --git a/drivers/staging/gpib/hp_82341/hp_82341.c b/drivers/staging/gpib/hp_82341/hp_82341.c deleted file mode 100644 index 1a2ad0560e14..000000000000 --- a/drivers/staging/gpib/hp_82341/hp_82341.c +++ /dev/null @@ -1,907 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * Driver for hp 82341a/b/c/d boards. * - * Might be worth merging with Agilent 82350b driver. * - * copyright : (C) 2002, 2005 by Frank Mori Hess * - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define DRV_NAME KBUILD_MODNAME - -#include "hp_82341.h" -#include <linux/delay.h> -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/isapnp.h> - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB driver for hp 82341a/b/c/d boards"); - -static unsigned short read_and_clear_event_status(struct gpib_board *board); -static void set_transfer_counter(struct hp_82341_priv *hp_priv, int count); -static int read_transfer_counter(struct hp_82341_priv *hp_priv); -static int hp_82341_write(struct gpib_board *board, u8 *buffer, size_t length, int send_eoi, - size_t *bytes_written); -static irqreturn_t hp_82341_interrupt(int irq, void *arg); - -static int hp_82341_accel_read(struct gpib_board *board, u8 *buffer, size_t length, int *end, - size_t *bytes_read) -{ - struct hp_82341_priv *hp_priv = board->private_data; - struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; - int retval = 0; - unsigned short event_status; - int i; - int num_fifo_bytes; - // hardware doesn't support checking for end-of-string character when using fifo - if (tms_priv->eos_flags & REOS) - return tms9914_read(board, tms_priv, buffer, length, end, bytes_read); - - clear_bit(DEV_CLEAR_BN, &tms_priv->state); - - read_and_clear_event_status(board); - *end = 0; - *bytes_read = 0; - if (length == 0) - return 0; - // disable fifo for the moment - outb(DIRECTION_GPIB_TO_HOST_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG); - /* - * Handle corner case of board not in holdoff and one byte has slipped in already. - * Also, board sometimes has problems (spurious 1 byte reads) when read fifo is - * started up with board in TACS under certain data holdoff conditions. - * Doing a 1 byte tms9914-style read avoids these problems. - */ - if (/*tms_priv->holdoff_active == 0 && */length > 1) { - size_t num_bytes; - - retval = tms9914_read(board, tms_priv, buffer, 1, end, &num_bytes); - *bytes_read += num_bytes; - if (retval < 0) - dev_err(board->gpib_dev, "tms9914_read failed retval=%i\n", retval); - if (retval < 0 || *end) - return retval; - ++buffer; - --length; - } - tms9914_set_holdoff_mode(tms_priv, TMS9914_HOLDOFF_EOI); - tms9914_release_holdoff(tms_priv); - outb(0x00, hp_priv->iobase[3] + BUFFER_FLUSH_REG); - i = 0; - num_fifo_bytes = length - 1; - while (i < num_fifo_bytes && *end == 0) { - int block_size; - int j; - int count; - - block_size = min(num_fifo_bytes - i, hp_82341_fifo_size); - set_transfer_counter(hp_priv, block_size); - outb(ENABLE_TI_BUFFER_BIT | DIRECTION_GPIB_TO_HOST_BIT, hp_priv->iobase[3] + - BUFFER_CONTROL_REG); - if (inb(hp_priv->iobase[0] + STREAM_STATUS_REG) & HALTED_STATUS_BIT) - outb(RESTART_STREAM_BIT, hp_priv->iobase[0] + STREAM_STATUS_REG); - - clear_bit(READ_READY_BN, &tms_priv->state); - - retval = wait_event_interruptible(board->wait, - ((event_status = - read_and_clear_event_status(board)) & - (TERMINAL_COUNT_EVENT_BIT | - BUFFER_END_EVENT_BIT)) || - test_bit(DEV_CLEAR_BN, &tms_priv->state) || - test_bit(TIMO_NUM, &board->status)); - if (retval) { - retval = -ERESTARTSYS; - break; - } - // have to disable buffer before we can read from buffer port - outb(DIRECTION_GPIB_TO_HOST_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG); - count = block_size - read_transfer_counter(hp_priv); - j = 0; - while (j < count && i < num_fifo_bytes) { - unsigned short data_word = inw(hp_priv->iobase[3] + BUFFER_PORT_LOW_REG); - - buffer[i++] = data_word & 0xff; - ++j; - if (j < count && i < num_fifo_bytes) { - buffer[i++] = (data_word >> 8) & 0xff; - ++j; - } - } - if (event_status & BUFFER_END_EVENT_BIT) { - clear_bit(RECEIVED_END_BN, &tms_priv->state); - - *end = 1; - tms_priv->holdoff_active = 1; - } - if (test_bit(TIMO_NUM, &board->status)) { - retval = -ETIMEDOUT; - break; - } - if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) { - retval = -EINTR; - break; - } - } - *bytes_read += i; - buffer += i; - length -= i; - if (retval < 0) - return retval; - // read last byte if we havn't received an END yet - if (*end == 0) { - size_t num_bytes; - // try to make sure we holdoff after last byte read - retval = tms9914_read(board, tms_priv, buffer, length, end, &num_bytes); - *bytes_read += num_bytes; - if (retval < 0) - return retval; - } - return 0; -} - -static int restart_write_fifo(struct gpib_board *board, struct hp_82341_priv *hp_priv) -{ - struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; - - if ((inb(hp_priv->iobase[0] + STREAM_STATUS_REG) & HALTED_STATUS_BIT) == 0) - return 0; - while (1) { - int status; - - // restart doesn't work if data holdoff is in effect - status = tms9914_line_status(board, tms_priv); - if ((status & BUS_NRFD) == 0) { - outb(RESTART_STREAM_BIT, hp_priv->iobase[0] + STREAM_STATUS_REG); - return 0; - } - if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) - return -EINTR; - if (test_bit(TIMO_NUM, &board->status)) - return -ETIMEDOUT; - if (msleep_interruptible(1)) - return -EINTR; - } - return 0; -} - -static int hp_82341_accel_write(struct gpib_board *board, u8 *buffer, size_t length, - int send_eoi, size_t *bytes_written) -{ - struct hp_82341_priv *hp_priv = board->private_data; - struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; - int i, j; - unsigned short event_status; - int retval = 0; - int fifo_xfer_len = length; - - *bytes_written = 0; - if (send_eoi) - --fifo_xfer_len; - - clear_bit(DEV_CLEAR_BN, &tms_priv->state); - - read_and_clear_event_status(board); - outb(0, hp_priv->iobase[3] + BUFFER_CONTROL_REG); - outb(0x00, hp_priv->iobase[3] + BUFFER_FLUSH_REG); - for (i = 0; i < fifo_xfer_len;) { - int block_size; - - block_size = min(fifo_xfer_len - i, hp_82341_fifo_size); - set_transfer_counter(hp_priv, block_size); - // load data into board's fifo - for (j = 0; j < block_size;) { - unsigned short data_word = buffer[i++]; - ++j; - if (j < block_size) { - data_word |= buffer[i++] << 8; - ++j; - } - outw(data_word, hp_priv->iobase[3] + BUFFER_PORT_LOW_REG); - } - clear_bit(WRITE_READY_BN, &tms_priv->state); - outb(ENABLE_TI_BUFFER_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG); - retval = restart_write_fifo(board, hp_priv); - if (retval < 0) { - dev_err(board->gpib_dev, "failed to restart write stream\n"); - break; - } - retval = wait_event_interruptible(board->wait, - ((event_status = - read_and_clear_event_status(board)) & - TERMINAL_COUNT_EVENT_BIT) || - test_bit(DEV_CLEAR_BN, &tms_priv->state) || - test_bit(TIMO_NUM, &board->status)); - outb(0, hp_priv->iobase[3] + BUFFER_CONTROL_REG); - *bytes_written += block_size - read_transfer_counter(hp_priv); - if (retval) { - retval = -ERESTARTSYS; - break; - } - if (test_bit(TIMO_NUM, &board->status)) { - retval = -ETIMEDOUT; - break; - } - if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) { - retval = -EINTR; - break; - } - } - if (retval) - return retval; - if (send_eoi) { - size_t num_bytes; - - retval = hp_82341_write(board, buffer + fifo_xfer_len, 1, 1, &num_bytes); - *bytes_written += num_bytes; - if (retval < 0) - return retval; - } - return 0; -} - -static int hp_82341_attach(struct gpib_board *board, const struct gpib_board_config *config); - -static void hp_82341_detach(struct gpib_board *board); - -// wrappers for interface functions -static int hp_82341_read(struct gpib_board *board, u8 *buffer, size_t length, int *end, - size_t *bytes_read) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read); -} - -static int hp_82341_write(struct gpib_board *board, u8 *buffer, size_t length, int send_eoi, - size_t *bytes_written) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written); -} - -static int hp_82341_command(struct gpib_board *board, u8 *buffer, size_t length, - size_t *bytes_written) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written); -} - -static int hp_82341_take_control(struct gpib_board *board, int synchronous) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_take_control(board, &priv->tms9914_priv, synchronous); -} - -static int hp_82341_go_to_standby(struct gpib_board *board) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_go_to_standby(board, &priv->tms9914_priv); -} - -static int hp_82341_request_system_control(struct gpib_board *board, int request_control) -{ - struct hp_82341_priv *priv = board->private_data; - - if (request_control) - priv->mode_control_bits |= SYSTEM_CONTROLLER_BIT; - else - priv->mode_control_bits &= ~SYSTEM_CONTROLLER_BIT; - outb(priv->mode_control_bits, priv->iobase[0] + MODE_CONTROL_STATUS_REG); - return tms9914_request_system_control(board, &priv->tms9914_priv, request_control); -} - -static void hp_82341_interface_clear(struct gpib_board *board, int assert) -{ - struct hp_82341_priv *priv = board->private_data; - - tms9914_interface_clear(board, &priv->tms9914_priv, assert); -} - -static void hp_82341_remote_enable(struct gpib_board *board, int enable) -{ - struct hp_82341_priv *priv = board->private_data; - - tms9914_remote_enable(board, &priv->tms9914_priv, enable); -} - -static int hp_82341_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits); -} - -static void hp_82341_disable_eos(struct gpib_board *board) -{ - struct hp_82341_priv *priv = board->private_data; - - tms9914_disable_eos(board, &priv->tms9914_priv); -} - -static unsigned int hp_82341_update_status(struct gpib_board *board, unsigned int clear_mask) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_update_status(board, &priv->tms9914_priv, clear_mask); -} - -static int hp_82341_primary_address(struct gpib_board *board, unsigned int address) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_primary_address(board, &priv->tms9914_priv, address); -} - -static int hp_82341_secondary_address(struct gpib_board *board, unsigned int address, int enable) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable); -} - -static int hp_82341_parallel_poll(struct gpib_board *board, u8 *result) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_parallel_poll(board, &priv->tms9914_priv, result); -} - -static void hp_82341_parallel_poll_configure(struct gpib_board *board, u8 config) -{ - struct hp_82341_priv *priv = board->private_data; - - tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config); -} - -static void hp_82341_parallel_poll_response(struct gpib_board *board, int ist) -{ - struct hp_82341_priv *priv = board->private_data; - - tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist); -} - -static void hp_82341_serial_poll_response(struct gpib_board *board, u8 status) -{ - struct hp_82341_priv *priv = board->private_data; - - tms9914_serial_poll_response(board, &priv->tms9914_priv, status); -} - -static u8 hp_82341_serial_poll_status(struct gpib_board *board) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_serial_poll_status(board, &priv->tms9914_priv); -} - -static int hp_82341_line_status(const struct gpib_board *board) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_line_status(board, &priv->tms9914_priv); -} - -static int hp_82341_t1_delay(struct gpib_board *board, unsigned int nano_sec) -{ - struct hp_82341_priv *priv = board->private_data; - - return tms9914_t1_delay(board, &priv->tms9914_priv, nano_sec); -} - -static void hp_82341_return_to_local(struct gpib_board *board) -{ - struct hp_82341_priv *priv = board->private_data; - - tms9914_return_to_local(board, &priv->tms9914_priv); -} - -static struct gpib_interface hp_82341_unaccel_interface = { - .name = "hp_82341_unaccel", - .attach = hp_82341_attach, - .detach = hp_82341_detach, - .read = hp_82341_read, - .write = hp_82341_write, - .command = hp_82341_command, - .request_system_control = hp_82341_request_system_control, - .take_control = hp_82341_take_control, - .go_to_standby = hp_82341_go_to_standby, - .interface_clear = hp_82341_interface_clear, - .remote_enable = hp_82341_remote_enable, - .enable_eos = hp_82341_enable_eos, - .disable_eos = hp_82341_disable_eos, - .parallel_poll = hp_82341_parallel_poll, - .parallel_poll_configure = hp_82341_parallel_poll_configure, - .parallel_poll_response = hp_82341_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = hp_82341_line_status, - .update_status = hp_82341_update_status, - .primary_address = hp_82341_primary_address, - .secondary_address = hp_82341_secondary_address, - .serial_poll_response = hp_82341_serial_poll_response, - .serial_poll_status = hp_82341_serial_poll_status, - .t1_delay = hp_82341_t1_delay, - .return_to_local = hp_82341_return_to_local, -}; - -static struct gpib_interface hp_82341_interface = { - .name = "hp_82341", - .attach = hp_82341_attach, - .detach = hp_82341_detach, - .read = hp_82341_accel_read, - .write = hp_82341_accel_write, - .command = hp_82341_command, - .request_system_control = hp_82341_request_system_control, - .take_control = hp_82341_take_control, - .go_to_standby = hp_82341_go_to_standby, - .interface_clear = hp_82341_interface_clear, - .remote_enable = hp_82341_remote_enable, - .enable_eos = hp_82341_enable_eos, - .disable_eos = hp_82341_disable_eos, - .parallel_poll = hp_82341_parallel_poll, - .parallel_poll_configure = hp_82341_parallel_poll_configure, - .parallel_poll_response = hp_82341_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = hp_82341_line_status, - .update_status = hp_82341_update_status, - .primary_address = hp_82341_primary_address, - .secondary_address = hp_82341_secondary_address, - .serial_poll_response = hp_82341_serial_poll_response, - .t1_delay = hp_82341_t1_delay, - .return_to_local = hp_82341_return_to_local, -}; - -static int hp_82341_allocate_private(struct gpib_board *board) -{ - board->private_data = kzalloc(sizeof(struct hp_82341_priv), GFP_KERNEL); - if (!board->private_data) - return -ENOMEM; - return 0; -} - -static void hp_82341_free_private(struct gpib_board *board) -{ - kfree(board->private_data); - board->private_data = NULL; -} - -static u8 hp_82341_read_byte(struct tms9914_priv *priv, unsigned int register_num) -{ - return inb(priv->iobase + register_num); -} - -static void hp_82341_write_byte(struct tms9914_priv *priv, u8 data, unsigned int register_num) -{ - outb(data, priv->iobase + register_num); -} - -static int hp_82341_find_isapnp_board(struct pnp_dev **dev) -{ - *dev = pnp_find_dev(NULL, ISAPNP_VENDOR('H', 'W', 'P'), - ISAPNP_FUNCTION(0x1411), NULL); - if (!*dev || !(*dev)->card) { - pr_err("failed to find isapnp board\n"); - return -ENODEV; - } - if (pnp_device_attach(*dev) < 0) { - pr_err("board already active, skipping\n"); - return -EBUSY; - } - if (pnp_activate_dev(*dev) < 0) { - pnp_device_detach(*dev); - pr_err("failed to activate(), aborting\n"); - return -EAGAIN; - } - if (!pnp_port_valid(*dev, 0) || !pnp_irq_valid(*dev, 0)) { - pnp_device_detach(*dev); - pr_err("invalid port or irq, aborting\n"); - return -ENOMEM; - } - return 0; -} - -static int xilinx_ready(struct hp_82341_priv *hp_priv) -{ - switch (hp_priv->hw_version) { - case HW_VERSION_82341C: - if (inb(hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG) & XILINX_READY_BIT) - return 1; - else - return 0; - break; - case HW_VERSION_82341D: - if (isapnp_read_byte(PIO_DATA_REG) & HP_82341D_XILINX_READY_BIT) - return 1; - else - return 0; - default: - pr_err("bug! unknown hw_version\n"); - break; - } - return 0; -} - -static int xilinx_done(struct hp_82341_priv *hp_priv) -{ - switch (hp_priv->hw_version) { - case HW_VERSION_82341C: - if (inb(hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG) & DONE_PGL_BIT) - return 1; - else - return 0; - case HW_VERSION_82341D: - if (isapnp_read_byte(PIO_DATA_REG) & HP_82341D_XILINX_DONE_BIT) - return 1; - else - return 0; - default: - pr_err("bug! unknown hw_version\n"); - break; - } - return 0; -} - -static int irq_valid(struct hp_82341_priv *hp_priv, int irq) -{ - switch (hp_priv->hw_version) { - case HW_VERSION_82341C: - switch (irq) { - case 3: - case 5: - case 7: - case 9: - case 10: - case 11: - case 12: - case 15: - return 1; - default: - pr_err("invalid irq=%i for 82341C, irq must be 3, 5, 7, 9, 10, 11, 12, or 15.\n", - irq); - return 0; - } - break; - case HW_VERSION_82341D: - return 1; - default: - pr_err("bug! unknown hw_version\n"); - break; - } - return 0; -} - -static int hp_82341_load_firmware_array(struct hp_82341_priv *hp_priv, - const unsigned char *firmware_data, - unsigned int firmware_length) -{ - int i, j; - static const int timeout = 100; - - for (i = 0; i < firmware_length; ++i) { - for (j = 0; j < timeout; ++j) { - if (need_resched()) - schedule(); - if (xilinx_ready(hp_priv)) - break; - usleep_range(10, 15); - } - if (j == timeout) { - pr_err("timed out waiting for Xilinx ready.\n"); - return -ETIMEDOUT; - } - outb(firmware_data[i], hp_priv->iobase[0] + XILINX_DATA_REG); - } - for (j = 0; j < timeout; ++j) { - if (xilinx_done(hp_priv)) - break; - if (need_resched()) - schedule(); - usleep_range(10, 15); - } - if (j == timeout) { - pr_err("timed out waiting for Xilinx done.\n"); - return -ETIMEDOUT; - } - return 0; -} - -static int hp_82341_load_firmware(struct hp_82341_priv *hp_priv, - const struct gpib_board_config *config) -{ - if (config->init_data_length == 0) { - if (xilinx_done(hp_priv)) - return 0; - pr_err("board needs be initialized with firmware upload.\n" - "\tUse the --init-data option of gpib_config.\n"); - return -EINVAL; - } - switch (hp_priv->hw_version) { - case HW_VERSION_82341C: - if (config->init_data_length != hp_82341c_firmware_length) { - pr_err("bad firmware length=%i for 82341c (expected %i).\n", - config->init_data_length, hp_82341c_firmware_length); - return -EINVAL; - } - break; - case HW_VERSION_82341D: - if (config->init_data_length != hp_82341d_firmware_length) { - pr_err("bad firmware length=%i for 82341d (expected %i).\n", - config->init_data_length, hp_82341d_firmware_length); - return -EINVAL; - } - break; - default: - pr_err("bug! unknown hw_version\n"); - break; - } - return hp_82341_load_firmware_array(hp_priv, config->init_data, config->init_data_length); -} - -static void set_xilinx_not_prog(struct hp_82341_priv *hp_priv, int assert) -{ - switch (hp_priv->hw_version) { - case HW_VERSION_82341C: - if (assert) - hp_priv->config_control_bits |= DONE_PGL_BIT; - else - hp_priv->config_control_bits &= ~DONE_PGL_BIT; - outb(hp_priv->config_control_bits, hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG); - break; - case HW_VERSION_82341D: - if (assert) - isapnp_write_byte(PIO_DATA_REG, HP_82341D_NOT_PROG_BIT); - else - isapnp_write_byte(PIO_DATA_REG, 0x0); - break; - default: - break; - } -} - -// clear xilinx firmware -static int clear_xilinx(struct hp_82341_priv *hp_priv) -{ - set_xilinx_not_prog(hp_priv, 1); - if (msleep_interruptible(1)) - return -EINTR; - set_xilinx_not_prog(hp_priv, 0); - if (msleep_interruptible(1)) - return -EINTR; - set_xilinx_not_prog(hp_priv, 1); - if (msleep_interruptible(1)) - return -EINTR; - return 0; -} - -static int hp_82341_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct hp_82341_priv *hp_priv; - struct tms9914_priv *tms_priv; - u32 start_addr; - u32 iobase; - int irq; - int i; - int retval; - - board->status = 0; - if (hp_82341_allocate_private(board)) - return -ENOMEM; - hp_priv = board->private_data; - tms_priv = &hp_priv->tms9914_priv; - tms_priv->read_byte = hp_82341_read_byte; - tms_priv->write_byte = hp_82341_write_byte; - tms_priv->offset = 1; - - if (config->ibbase == 0) { - struct pnp_dev *dev; - int retval = hp_82341_find_isapnp_board(&dev); - - if (retval < 0) - return retval; - hp_priv->pnp_dev = dev; - iobase = pnp_port_start(dev, 0); - irq = pnp_irq(dev, 0); - hp_priv->hw_version = HW_VERSION_82341D; - hp_priv->io_region_offset = 0x8; - } else { - iobase = config->ibbase; - irq = config->ibirq; - hp_priv->hw_version = HW_VERSION_82341C; - hp_priv->io_region_offset = 0x400; - } - for (i = 0; i < hp_82341_num_io_regions; ++i) { - start_addr = iobase + i * hp_priv->io_region_offset; - if (!request_region(start_addr, hp_82341_region_iosize, DRV_NAME)) { - dev_err(board->gpib_dev, "failed to allocate io ports 0x%x-0x%x\n", - start_addr, - start_addr + hp_82341_region_iosize - 1); - return -EIO; - } - hp_priv->iobase[i] = start_addr; - } - tms_priv->iobase = hp_priv->iobase[2]; - if (hp_priv->hw_version == HW_VERSION_82341D) { - retval = isapnp_cfg_begin(hp_priv->pnp_dev->card->number, - hp_priv->pnp_dev->number); - if (retval < 0) { - dev_err(board->gpib_dev, "isapnp_cfg_begin returned error\n"); - return retval; - } - isapnp_write_byte(PIO_DIRECTION_REG, HP_82341D_XILINX_READY_BIT | - HP_82341D_XILINX_DONE_BIT); - } - retval = clear_xilinx(hp_priv); - if (retval < 0) - return retval; - retval = hp_82341_load_firmware(hp_priv, config); - if (hp_priv->hw_version == HW_VERSION_82341D) - isapnp_cfg_end(); - if (retval < 0) - return retval; - if (irq_valid(hp_priv, irq) == 0) - return -EINVAL; - if (request_irq(irq, hp_82341_interrupt, 0, DRV_NAME, board)) { - dev_err(board->gpib_dev, "failed to allocate IRQ %d\n", irq); - return -EIO; - } - hp_priv->irq = irq; - hp_priv->config_control_bits &= ~IRQ_SELECT_MASK; - hp_priv->config_control_bits |= IRQ_SELECT_BITS(irq); - outb(hp_priv->config_control_bits, hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG); - hp_priv->mode_control_bits |= ENABLE_IRQ_CONFIG_BIT; - outb(hp_priv->mode_control_bits, hp_priv->iobase[0] + MODE_CONTROL_STATUS_REG); - tms9914_board_reset(tms_priv); - outb(ENABLE_BUFFER_END_EVENT_BIT | ENABLE_TERMINAL_COUNT_EVENT_BIT | - ENABLE_TI_INTERRUPT_EVENT_BIT, hp_priv->iobase[0] + EVENT_ENABLE_REG); - outb(ENABLE_BUFFER_END_INTERRUPT_BIT | ENABLE_TERMINAL_COUNT_INTERRUPT_BIT | - ENABLE_TI_INTERRUPT_BIT, hp_priv->iobase[0] + INTERRUPT_ENABLE_REG); - // write clear event register - outb((TI_INTERRUPT_EVENT_BIT | POINTERS_EQUAL_EVENT_BIT | - BUFFER_END_EVENT_BIT | TERMINAL_COUNT_EVENT_BIT), - hp_priv->iobase[0] + EVENT_STATUS_REG); - - tms9914_online(board, tms_priv); - - return 0; -} - -static void hp_82341_detach(struct gpib_board *board) -{ - struct hp_82341_priv *hp_priv = board->private_data; - struct tms9914_priv *tms_priv; - int i; - - if (hp_priv) { - tms_priv = &hp_priv->tms9914_priv; - if (hp_priv->iobase[0]) { - outb(0, hp_priv->iobase[0] + INTERRUPT_ENABLE_REG); - if (tms_priv->iobase) - tms9914_board_reset(tms_priv); - if (hp_priv->irq) - free_irq(hp_priv->irq, board); - } - for (i = 0; i < hp_82341_num_io_regions; ++i) { - if (hp_priv->iobase[i]) - release_region(hp_priv->iobase[i], hp_82341_region_iosize); - } - if (hp_priv->pnp_dev) - pnp_device_detach(hp_priv->pnp_dev); - } - hp_82341_free_private(board); -} - -#if 0 -/* unused, will be needed when the driver is turned into a pnp_driver */ -static const struct pnp_device_id hp_82341_pnp_table[] = { - {.id = "HWP1411"}, - {.id = ""} -}; -MODULE_DEVICE_TABLE(pnp, hp_82341_pnp_table); -#endif - -static int __init hp_82341_init_module(void) -{ - int ret; - - ret = gpib_register_driver(&hp_82341_unaccel_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - return ret; - } - - ret = gpib_register_driver(&hp_82341_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - gpib_unregister_driver(&hp_82341_unaccel_interface); - return ret; - } - - return 0; -} - -static void __exit hp_82341_exit_module(void) -{ - gpib_unregister_driver(&hp_82341_interface); - gpib_unregister_driver(&hp_82341_unaccel_interface); -} - -module_init(hp_82341_init_module); -module_exit(hp_82341_exit_module); - -/* - * GPIB interrupt service routines - */ -static unsigned short read_and_clear_event_status(struct gpib_board *board) -{ - struct hp_82341_priv *hp_priv = board->private_data; - unsigned long flags; - unsigned short status; - - spin_lock_irqsave(&board->spinlock, flags); - status = hp_priv->event_status_bits; - hp_priv->event_status_bits = 0; - spin_unlock_irqrestore(&board->spinlock, flags); - return status; -} - -static irqreturn_t hp_82341_interrupt(int irq, void *arg) -{ - int status1, status2; - struct gpib_board *board = arg; - struct hp_82341_priv *hp_priv = board->private_data; - struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv; - unsigned long flags; - irqreturn_t retval = IRQ_NONE; - int event_status; - - spin_lock_irqsave(&board->spinlock, flags); - event_status = inb(hp_priv->iobase[0] + EVENT_STATUS_REG); - if (event_status & INTERRUPT_PENDING_EVENT_BIT) - retval = IRQ_HANDLED; - // write-clear status bits - if (event_status & (TI_INTERRUPT_EVENT_BIT | POINTERS_EQUAL_EVENT_BIT | - BUFFER_END_EVENT_BIT | TERMINAL_COUNT_EVENT_BIT)) { - outb(event_status & (TI_INTERRUPT_EVENT_BIT | POINTERS_EQUAL_EVENT_BIT | - BUFFER_END_EVENT_BIT | TERMINAL_COUNT_EVENT_BIT), - hp_priv->iobase[0] + EVENT_STATUS_REG); - hp_priv->event_status_bits |= event_status; - } - if (event_status & TI_INTERRUPT_EVENT_BIT) { - status1 = read_byte(tms_priv, ISR0); - status2 = read_byte(tms_priv, ISR1); - tms9914_interrupt_have_status(board, tms_priv, status1, status2); - } - spin_unlock_irqrestore(&board->spinlock, flags); - return retval; -} - -static int read_transfer_counter(struct hp_82341_priv *hp_priv) -{ - int lo, mid, value; - - lo = inb(hp_priv->iobase[1] + TRANSFER_COUNT_LOW_REG); - mid = inb(hp_priv->iobase[1] + TRANSFER_COUNT_MID_REG); - value = (lo & 0xff) | ((mid << 8) & 0x7f00); - value = ~(value - 1) & 0x7fff; - return value; -} - -static void set_transfer_counter(struct hp_82341_priv *hp_priv, int count) -{ - int complement = -count; - - outb(complement & 0xff, hp_priv->iobase[1] + TRANSFER_COUNT_LOW_REG); - outb((complement >> 8) & 0xff, hp_priv->iobase[1] + TRANSFER_COUNT_MID_REG); - // I don't think the hi count reg is even used, but oh well - outb((complement >> 16) & 0xf, hp_priv->iobase[1] + TRANSFER_COUNT_HIGH_REG); -} - diff --git a/drivers/staging/gpib/hp_82341/hp_82341.h b/drivers/staging/gpib/hp_82341/hp_82341.h deleted file mode 100644 index 859ef2899acb..000000000000 --- a/drivers/staging/gpib/hp_82341/hp_82341.h +++ /dev/null @@ -1,165 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002, 2005 by Frank Mori Hess * - ***************************************************************************/ - -#include "tms9914.h" -#include "gpibP.h" - -enum hp_82341_hardware_version { - HW_VERSION_UNKNOWN, - HW_VERSION_82341C, - HW_VERSION_82341D, -}; - -// struct which defines private_data for board -struct hp_82341_priv { - struct tms9914_priv tms9914_priv; - unsigned int irq; - unsigned short config_control_bits; - unsigned short mode_control_bits; - unsigned short event_status_bits; - struct pnp_dev *pnp_dev; - unsigned long iobase[4]; - unsigned long io_region_offset; - enum hp_82341_hardware_version hw_version; -}; - -static const int hp_82341_region_iosize = 0x8; -static const int hp_82341_num_io_regions = 4; -static const int hp_82341_fifo_size = 0xffe; -static const int hp_82341c_firmware_length = 5764; -static const int hp_82341d_firmware_length = 5302; - -// hp 82341 register offsets -enum hp_82341_region_0_registers { - CONFIG_CONTROL_STATUS_REG = 0x0, - MODE_CONTROL_STATUS_REG = 0x1, - MONITOR_REG = 0x2, // after initialization - XILINX_DATA_REG = 0x2, // before initialization, write only - INTERRUPT_ENABLE_REG = 0x3, - EVENT_STATUS_REG = 0x4, - EVENT_ENABLE_REG = 0x5, - STREAM_STATUS_REG = 0x7, -}; - -enum hp_82341_region_1_registers { - ID0_REG = 0x2, - ID1_REG = 0x3, - TRANSFER_COUNT_LOW_REG = 0x4, - TRANSFER_COUNT_MID_REG = 0x5, - TRANSFER_COUNT_HIGH_REG = 0x6, -}; - -enum hp_82341_region_3_registers { - BUFFER_PORT_LOW_REG = 0x0, - BUFFER_PORT_HIGH_REG = 0x1, - ID2_REG = 0x2, - ID3_REG = 0x3, - BUFFER_FLUSH_REG = 0x4, - BUFFER_CONTROL_REG = 0x7 -}; - -enum config_control_status_bits { - IRQ_SELECT_MASK = 0x7, - DMA_CONFIG_MASK = 0x18, - ENABLE_DMA_CONFIG_BIT = 0x20, - XILINX_READY_BIT = 0x40, // read only - DONE_PGL_BIT = 0x80 -}; - -static inline unsigned int IRQ_SELECT_BITS(int irq) -{ - switch (irq) { - case 3: - return 0x3; - case 5: - return 0x2; - case 7: - return 0x1; - case 9: - return 0x0; - case 10: - return 0x7; - case 11: - return 0x6; - case 12: - return 0x5; - case 15: - return 0x4; - default: - return 0x0; - } -}; - -enum mode_control_status_bits { - SLOT8_BIT = 0x1, // read only - ACTIVE_CONTROLLER_BIT = 0x2, // read only - ENABLE_DMA_BIT = 0x4, - SYSTEM_CONTROLLER_BIT = 0x8, - MONITOR_BIT = 0x10, - ENABLE_IRQ_CONFIG_BIT = 0x20, - ENABLE_TI_STREAM_BIT = 0x40 -}; - -enum monitor_bits { - MONITOR_INTERRUPT_PENDING_BIT = 0x1, // read only - MONITOR_CLEAR_HOLDOFF_BIT = 0x2, // write only - MONITOR_PPOLL_BIT = 0x4, // write clear - MONITOR_SRQ_BIT = 0x8, // write clear - MONITOR_IFC_BIT = 0x10, // write clear - MONITOR_REN_BIT = 0x20, // write clear - MONITOR_END_BIT = 0x40, // write clear - MONITOR_DAV_BIT = 0x80 // write clear -}; - -enum interrupt_enable_bits { - ENABLE_TI_INTERRUPT_BIT = 0x1, - ENABLE_POINTERS_EQUAL_INTERRUPT_BIT = 0x4, - ENABLE_BUFFER_END_INTERRUPT_BIT = 0x10, - ENABLE_TERMINAL_COUNT_INTERRUPT_BIT = 0x20, - ENABLE_DMA_TERMINAL_COUNT_INTERRUPT_BIT = 0x80, -}; - -enum event_status_bits { - TI_INTERRUPT_EVENT_BIT = 0x1, // write clear - INTERRUPT_PENDING_EVENT_BIT = 0x2, // read only - POINTERS_EQUAL_EVENT_BIT = 0x4, // write clear - BUFFER_END_EVENT_BIT = 0x10, // write clear - TERMINAL_COUNT_EVENT_BIT = 0x20, // write clear - DMA_TERMINAL_COUNT_EVENT_BIT = 0x80, // write clear -}; - -enum event_enable_bits { - ENABLE_TI_INTERRUPT_EVENT_BIT = 0x1, // write clear - ENABLE_POINTERS_EQUAL_EVENT_BIT = 0x4, // write clear - ENABLE_BUFFER_END_EVENT_BIT = 0x10, // write clear - ENABLE_TERMINAL_COUNT_EVENT_BIT = 0x20, // write clear - ENABLE_DMA_TERMINAL_COUNT_EVENT_BIT = 0x80, // write clear -}; - -enum stream_status_bits { - HALTED_STATUS_BIT = 0x1, // read - RESTART_STREAM_BIT = 0x1 // write -}; - -enum buffer_control_bits { - DIRECTION_GPIB_TO_HOST_BIT = 0x20, // transfer direction (set for gpib to host) - ENABLE_TI_BUFFER_BIT = 0x40, // enable fifo - FAST_WR_EN_BIT = 0x80, // 350 ns t1 delay? -}; - -// registers accessible through isapnp chip on 82341d -enum hp_82341d_pnp_registers { - PIO_DATA_REG = 0x20, // read/write pio data lines - PIO_DIRECTION_REG = 0x21, // set pio data line directions (set for input) -}; - -enum hp_82341d_pnp_pio_bits { - HP_82341D_XILINX_READY_BIT = 0x1, - HP_82341D_XILINX_DONE_BIT = 0x2, - // use register layout compatible with C and older versions instead of 32 contiguous ioports - HP_82341D_LEGACY_MODE_BIT = 0x4, - HP_82341D_NOT_PROG_BIT = 0x8, // clear to reinitialize xilinx -}; diff --git a/drivers/staging/gpib/include/amcc5920.h b/drivers/staging/gpib/include/amcc5920.h deleted file mode 100644 index 7a88bd282feb..000000000000 --- a/drivers/staging/gpib/include/amcc5920.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * Header for amcc5920 pci chip - * - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -// plx pci chip registers and bits -enum amcc_registers { - AMCC_INTCS_REG = 0x38, - AMCC_PASS_THRU_REG = 0x60, -}; - -enum amcc_incsr_bits { - AMCC_ADDON_INTR_ENABLE_BIT = 0x2000, - AMCC_ADDON_INTR_ACTIVE_BIT = 0x400000, - AMCC_INTR_ACTIVE_BIT = 0x800000, -}; - -static const int bits_per_region = 8; - -static inline uint32_t amcc_wait_state_bits(unsigned int region, unsigned int num_wait_states) -{ - return (num_wait_states & 0x7) << (--region * bits_per_region); -}; - -enum amcc_prefetch_bits { - PREFETCH_DISABLED = 0x0, - PREFETCH_SMALL = 0x8, - PREFETCH_MEDIUM = 0x10, - PREFETCH_LARGE = 0x18, -}; - -static inline uint32_t amcc_prefetch_bits(unsigned int region, enum amcc_prefetch_bits prefetch) -{ - return prefetch << (--region * bits_per_region); -}; - -static inline uint32_t amcc_PTADR_mode_bit(unsigned int region) -{ - return 0x80 << (--region * bits_per_region); -}; - -static inline uint32_t amcc_disable_write_fifo_bit(unsigned int region) -{ - return 0x20 << (--region * bits_per_region); -}; - diff --git a/drivers/staging/gpib/include/amccs5933.h b/drivers/staging/gpib/include/amccs5933.h deleted file mode 100644 index d7f63c795096..000000000000 --- a/drivers/staging/gpib/include/amccs5933.h +++ /dev/null @@ -1,59 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * Registers and bits for amccs5933 pci chip - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -// register offsets -enum { - MBEF_REG = 0x34, // mailbux empty/full - INTCSR_REG = 0x38, // interrupt control and status - BMCSR_REG = 0x3c, // bus master control and status -}; - -// incoming mailbox 0-3 register offsets -extern inline int INCOMING_MAILBOX_REG(unsigned int mailbox) -{ - return (0x10 + 4 * mailbox); -}; - -// bit definitions - -// INTCSR bits -enum { - OUTBOX_EMPTY_INTR_BIT = 0x10, // enable outbox empty interrupt - INBOX_FULL_INTR_BIT = 0x1000, // enable inbox full interrupt - INBOX_INTR_CS_BIT = 0x20000, // read, or write clear inbox full interrupt - INTR_ASSERTED_BIT = 0x800000, // read only, interrupt asserted -}; - -// select byte 0 to 3 of incoming mailbox -extern inline int INBOX_BYTE_BITS(unsigned int byte) -{ - return (byte & 0x3) << 8; -}; - -// select incoming mailbox 0 to 3 -extern inline int INBOX_SELECT_BITS(unsigned int mailbox) -{ - return (mailbox & 0x3) << 10; -}; - -// select byte 0 to 3 of outgoing mailbox -extern inline int OUTBOX_BYTE_BITS(unsigned int byte) -{ - return (byte & 0x3); -}; - -// select outgoing mailbox 0 to 3 -extern inline int OUTBOX_SELECT_BITS(unsigned int mailbox) -{ - return (mailbox & 0x3) << 2; -}; - -// BMCSR bits -enum { - MBOX_FLAGS_RESET_BIT = 0x08000000, // resets mailbox empty/full flags -}; - diff --git a/drivers/staging/gpib/include/gpibP.h b/drivers/staging/gpib/include/gpibP.h deleted file mode 100644 index 1b27f37e0ba0..000000000000 --- a/drivers/staging/gpib/include/gpibP.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002,2003 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _GPIB_P_H -#define _GPIB_P_H - -#include <linux/types.h> - -#include "gpib_types.h" -#include "gpib_proto.h" -#include "gpib_cmd.h" -#include "gpib.h" -#include "gpib_ioctl.h" - -#include <linux/fs.h> -#include <linux/interrupt.h> -#include <linux/io.h> - -int gpib_register_driver(struct gpib_interface *interface, struct module *mod); -void gpib_unregister_driver(struct gpib_interface *interface); -struct pci_dev *gpib_pci_get_device(const struct gpib_board_config *config, unsigned int vendor_id, - unsigned int device_id, struct pci_dev *from); -struct pci_dev *gpib_pci_get_subsys(const struct gpib_board_config *config, unsigned int vendor_id, - unsigned int device_id, unsigned int ss_vendor, - unsigned int ss_device, struct pci_dev *from); -unsigned int num_gpib_events(const struct gpib_event_queue *queue); -int push_gpib_event(struct gpib_board *board, short event_type); -int pop_gpib_event(struct gpib_board *board, struct gpib_event_queue *queue, short *event_type); -int gpib_request_pseudo_irq(struct gpib_board *board, irqreturn_t (*handler)(int, void *)); -void gpib_free_pseudo_irq(struct gpib_board *board); -int gpib_match_device_path(struct device *dev, const char *device_path_in); - -extern struct gpib_board board_array[GPIB_MAX_NUM_BOARDS]; - -extern struct list_head registered_drivers; - -#endif // _GPIB_P_H - diff --git a/drivers/staging/gpib/include/gpib_cmd.h b/drivers/staging/gpib/include/gpib_cmd.h deleted file mode 100644 index 9e96a3bfa22d..000000000000 --- a/drivers/staging/gpib/include/gpib_cmd.h +++ /dev/null @@ -1,112 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#ifndef _GPIB_CMD_H -#define _GPIB_CMD_H - -#include <linux/types.h> - -/* Command byte definitions tests and functions */ - -/* mask of bits that actually matter in a command byte */ -enum { - gpib_command_mask = 0x7f, -}; - -/* Possible GPIB command messages */ - -enum cmd_byte { - GTL = 0x1, /* go to local */ - SDC = 0x4, /* selected device clear */ - PP_CONFIG = 0x5, - GET = 0x8, /* group execute trigger */ - TCT = 0x9, /* take control */ - LLO = 0x11, /* local lockout */ - DCL = 0x14, /* device clear */ - PPU = 0x15, /* parallel poll unconfigure */ - SPE = 0x18, /* serial poll enable */ - SPD = 0x19, /* serial poll disable */ - CFE = 0x1f, /* configure enable */ - LAD = 0x20, /* value to be 'ored' in to obtain listen address */ - UNL = 0x3F, /* unlisten */ - TAD = 0x40, /* value to be 'ored' in to obtain talk address */ - UNT = 0x5F, /* untalk */ - SAD = 0x60, /* my secondary address (base) */ - PPE = 0x60, /* parallel poll enable (base) */ - PPD = 0x70 /* parallel poll disable */ -}; - -/* confine address to range 0 to 30. */ -static inline unsigned int gpib_address_restrict(u32 addr) -{ - addr &= 0x1f; - if (addr == 0x1f) - addr = 0; - return addr; -} - -static inline u8 MLA(u32 addr) -{ - return gpib_address_restrict(addr) | LAD; -} - -static inline u8 MTA(u32 addr) -{ - return gpib_address_restrict(addr) | TAD; -} - -static inline u8 MSA(u32 addr) -{ - return (addr & 0x1f) | SAD; -} - -static inline s32 gpib_address_equal(u32 pad1, s32 sad1, u32 pad2, s32 sad2) -{ - if (pad1 == pad2) { - if (sad1 == sad2) - return 1; - if (sad1 < 0 && sad2 < 0) - return 1; - } - - return 0; -} - -static inline s32 is_PPE(u8 command) -{ - return (command & 0x70) == 0x60; -} - -static inline s32 is_PPD(u8 command) -{ - return (command & 0x70) == 0x70; -} - -static inline s32 in_addressed_command_group(u8 command) -{ - return (command & 0x70) == 0x0; -} - -static inline s32 in_universal_command_group(u8 command) -{ - return (command & 0x70) == 0x10; -} - -static inline s32 in_listen_address_group(u8 command) -{ - return (command & 0x60) == 0x20; -} - -static inline s32 in_talk_address_group(u8 command) -{ - return (command & 0x60) == 0x40; -} - -static inline s32 in_primary_command_group(u8 command) -{ - return in_addressed_command_group(command) || - in_universal_command_group(command) || - in_listen_address_group(command) || - in_talk_address_group(command); -} - -#endif /* _GPIB_CMD_H */ diff --git a/drivers/staging/gpib/include/gpib_pci_ids.h b/drivers/staging/gpib/include/gpib_pci_ids.h deleted file mode 100644 index 52dcab07a7d1..000000000000 --- a/drivers/staging/gpib/include/gpib_pci_ids.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#ifndef __GPIB_PCI_IDS_H -#define __GPIB_PCI_IDS_H - -#ifndef PCI_VENDOR_ID_AMCC -#define PCI_VENDOR_ID_AMCC 0x10e8 -#endif - -#ifndef PCI_VENDOR_ID_CBOARDS -#define PCI_VENDOR_ID_CBOARDS 0x1307 -#endif - -#ifndef PCI_VENDOR_ID_QUANCOM -#define PCI_VENDOR_ID_QUANCOM 0x8008 -#endif - -#ifndef PCI_DEVICE_ID_QUANCOM_GPIB -#define PCI_DEVICE_ID_QUANCOM_GPIB 0x3302 -#endif - -#endif // __GPIB_PCI_IDS_H - diff --git a/drivers/staging/gpib/include/gpib_proto.h b/drivers/staging/gpib/include/gpib_proto.h deleted file mode 100644 index 42e736e3b7cd..000000000000 --- a/drivers/staging/gpib/include/gpib_proto.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#ifndef GPIB_PROTO_INCLUDED -#define GPIB_PROTO_INCLUDED - -#include <linux/fs.h> - -int ibopen(struct inode *inode, struct file *filep); -int ibclose(struct inode *inode, struct file *file); -long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg); -void os_start_timer(struct gpib_board *board, unsigned int usec_timeout); -void os_remove_timer(struct gpib_board *board); -void init_gpib_board(struct gpib_board *board); -static inline unsigned long usec_to_jiffies(unsigned int usec) -{ - unsigned long usec_per_jiffy = 1000000 / HZ; - - return 1 + (usec + usec_per_jiffy - 1) / usec_per_jiffy; -}; - -int serial_poll_all(struct gpib_board *board, unsigned int usec_timeout); -void init_gpib_descriptor(struct gpib_descriptor *desc); -int dvrsp(struct gpib_board *board, unsigned int pad, int sad, - unsigned int usec_timeout, u8 *result); -int ibcac(struct gpib_board *board, int sync, int fallback_to_async); -int ibcmd(struct gpib_board *board, u8 *buf, size_t length, size_t *bytes_written); -int ibgts(struct gpib_board *board); -int ibonline(struct gpib_board *board); -int iboffline(struct gpib_board *board); -int iblines(const struct gpib_board *board, short *lines); -int ibrd(struct gpib_board *board, u8 *buf, size_t length, int *end_flag, size_t *bytes_read); -int ibrpp(struct gpib_board *board, u8 *buf); -int ibrsv2(struct gpib_board *board, u8 status_byte, int new_reason_for_service); -int ibrsc(struct gpib_board *board, int request_control); -int ibsic(struct gpib_board *board, unsigned int usec_duration); -int ibsre(struct gpib_board *board, int enable); -int ibpad(struct gpib_board *board, unsigned int addr); -int ibsad(struct gpib_board *board, int addr); -int ibeos(struct gpib_board *board, int eos, int eosflags); -int ibwait(struct gpib_board *board, int wait_mask, int clear_mask, int set_mask, - int *status, unsigned long usec_timeout, struct gpib_descriptor *desc); -int ibwrt(struct gpib_board *board, u8 *buf, size_t cnt, int send_eoi, size_t *bytes_written); -int ibstatus(struct gpib_board *board); -int general_ibstatus(struct gpib_board *board, const struct gpib_status_queue *device, - int clear_mask, int set_mask, struct gpib_descriptor *desc); -int io_timed_out(struct gpib_board *board); -int ibppc(struct gpib_board *board, u8 configuration); - -#endif /* GPIB_PROTO_INCLUDED */ diff --git a/drivers/staging/gpib/include/gpib_state_machines.h b/drivers/staging/gpib/include/gpib_state_machines.h deleted file mode 100644 index 7488c00f191e..000000000000 --- a/drivers/staging/gpib/include/gpib_state_machines.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2006 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _GPIB_STATE_MACHINES_H -#define _GPIB_STATE_MACHINES_H - -enum talker_function_state { - talker_idle, - talker_addressed, - talker_active, - serial_poll_active -}; - -enum listener_function_state { - listener_idle, - listener_addressed, - listener_active -}; - -#endif // _GPIB_STATE_MACHINES_H diff --git a/drivers/staging/gpib/include/gpib_types.h b/drivers/staging/gpib/include/gpib_types.h deleted file mode 100644 index 998abb379749..000000000000 --- a/drivers/staging/gpib/include/gpib_types.h +++ /dev/null @@ -1,381 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _GPIB_TYPES_H -#define _GPIB_TYPES_H - -#ifdef __KERNEL__ -#include "gpib.h" -#include <linux/atomic.h> -#include <linux/device.h> -#include <linux/mutex.h> -#include <linux/wait.h> -#include <linux/sched.h> -#include <linux/timer.h> -#include <linux/interrupt.h> - -struct gpib_board; - -/* config parameters that are only used by driver attach functions */ -struct gpib_board_config { - /* firmware blob */ - void *init_data; - int init_data_length; - /* IO base address to use for non-pnp cards (set by core, driver should make local copy) */ - u32 ibbase; - void __iomem *mmibbase; - /* IRQ to use for non-pnp cards (set by core, driver should make local copy) */ - unsigned int ibirq; - /* dma channel to use for non-pnp cards (set by core, driver should make local copy) */ - unsigned int ibdma; - /* - * pci bus of card, useful for distinguishing multiple identical pci cards - * (negative means don't care) - */ - int pci_bus; - /* - * pci slot of card, useful for distinguishing multiple identical pci cards - * (negative means don't care) - */ - int pci_slot; - /* sysfs device path of hardware to attach */ - char *device_path; - /* serial number of hardware to attach */ - char *serial_number; -}; - -/* - * struct gpib_interface defines the interface - * between the board-specific details dealt with in the drivers - * and generic interface provided by gpib-common. - * This really should be in a different header file. - */ -struct gpib_interface { - /* name of board */ - char *name; - /* attach() initializes board and allocates resources */ - int (*attach)(struct gpib_board *board, const struct gpib_board_config *config); - /* detach() shuts down board and frees resources */ - void (*detach)(struct gpib_board *board); - /* - * read() should read at most 'length' bytes from the bus into - * 'buffer'. It should return when it fills the buffer or - * encounters an END (EOI and or EOS if appropriate). It should set 'end' - * to be nonzero if the read was terminated by an END, otherwise 'end' - * should be zero. - * Ultimately, this will be changed into or replaced by an asynchronous - * read. Zero return value for success, negative - * return indicates error. - * nbytes returns number of bytes read - */ - int (*read)(struct gpib_board *board, u8 *buffer, size_t length, int *end, - size_t *bytes_read); - /* - * write() should write 'length' bytes from buffer to the bus. - * If the boolean value send_eoi is nonzero, then EOI should - * be sent along with the last byte. Returns number of bytes - * written or negative value on error. - */ - int (*write)(struct gpib_board *board, u8 *buffer, size_t length, int send_eoi, - size_t *bytes_written); - /* - * command() writes the command bytes in 'buffer' to the bus - * Returns zero on success or negative value on error. - */ - int (*command)(struct gpib_board *board, u8 *buffer, size_t length, - size_t *bytes_written); - /* - * Take control (assert ATN). If 'asyncronous' is nonzero, take - * control asyncronously (assert ATN immediately without waiting - * for other processes to complete first). Should not return - * until board becomes controller in charge. Returns zero no success, - * nonzero on error. - */ - int (*take_control)(struct gpib_board *board, int asyncronous); - /* - * De-assert ATN. Returns zero on success, nonzer on error. - */ - int (*go_to_standby)(struct gpib_board *board); - /* request/release control of the IFC and REN lines (system controller) */ - int (*request_system_control)(struct gpib_board *board, int request_control); - /* - * Asserts or de-asserts 'interface clear' (IFC) depending on - * boolean value of 'assert' - */ - void (*interface_clear)(struct gpib_board *board, int assert); - /* - * Sends remote enable command if 'enable' is nonzero, disables remote mode - * if 'enable' is zero - */ - void (*remote_enable)(struct gpib_board *board, int enable); - /* - * enable END for reads, when byte 'eos' is received. If - * 'compare_8_bits' is nonzero, then all 8 bits are compared - * with the eos bytes. Otherwise only the 7 least significant - * bits are compared. - */ - int (*enable_eos)(struct gpib_board *board, u8 eos, int compare_8_bits); - /* disable END on eos byte (END on EOI only)*/ - void (*disable_eos)(struct gpib_board *board); - /* configure parallel poll */ - void (*parallel_poll_configure)(struct gpib_board *board, u8 configuration); - /* conduct parallel poll */ - int (*parallel_poll)(struct gpib_board *board, u8 *result); - /* set/clear ist (individual status bit) */ - void (*parallel_poll_response)(struct gpib_board *board, int ist); - /* select local parallel poll configuration mode PP2 versus remote PP1 */ - void (*local_parallel_poll_mode)(struct gpib_board *board, int local); - /* - * Returns current status of the bus lines. Should be set to - * NULL if your board does not have the ability to query the - * state of the bus lines. - */ - int (*line_status)(const struct gpib_board *board); - /* - * updates and returns the board's current status. - * The meaning of the bits are specified in gpib_user.h - * in the IBSTA section. The driver does not need to - * worry about setting the CMPL, END, TIMO, or ERR bits. - */ - unsigned int (*update_status)(struct gpib_board *board, unsigned int clear_mask); - /* - * Sets primary address 0-30 for gpib interface card. - */ - int (*primary_address)(struct gpib_board *board, unsigned int address); - /* - * Sets and enables, or disables secondary address 0-30 - * for gpib interface card. - */ - int (*secondary_address)(struct gpib_board *board, unsigned int address, - int enable); - /* - * Sets the byte the board should send in response to a serial poll. - * This function should also start or stop requests for service via - * IEEE 488.2 reqt/reqf, based on MSS (bit 6 of the status_byte). - * If the more flexible serial_poll_response2 is implemented by the - * driver, then this method should be left NULL since it will not - * be used. This method can generate spurious service requests - * which are allowed by IEEE 488.2, but not ideal. - * - * This method should implement the serial poll response method described - * by IEEE 488.2 section 11.3.3.4.3 "Allowed Coupled Control of - * STB, reqt, and reqf". - */ - void (*serial_poll_response)(struct gpib_board *board, u8 status_byte); - /* - * Sets the byte the board should send in response to a serial poll. - * This function should also request service via IEEE 488.2 reqt/reqf - * based on MSS (bit 6 of the status_byte) and new_reason_for_service. - * reqt should be set true if new_reason_for_service is true, - * and reqf should be set true if MSS is false. This function - * will never be called with MSS false and new_reason_for_service - * true simultaneously, so don't worry about that case. - * - * This method implements the serial poll response method described - * by IEEE 488.2 section 11.3.3.4.1 "Preferred Implementation". - * - * If this method is left NULL by the driver, then the user library - * function ibrsv2 will not work. - */ - void (*serial_poll_response2)(struct gpib_board *board, u8 status_byte, - int new_reason_for_service); - /* - * returns the byte the board will send in response to a serial poll. - */ - u8 (*serial_poll_status)(struct gpib_board *board); - /* adjust T1 delay */ - int (*t1_delay)(struct gpib_board *board, unsigned int nano_sec); - /* go to local mode */ - void (*return_to_local)(struct gpib_board *board); - /* board does not support 7 bit eos comparisons */ - unsigned no_7_bit_eos : 1; - /* skip check for listeners before trying to send command bytes */ - unsigned skip_check_for_command_acceptors : 1; -}; - -struct gpib_event_queue { - struct list_head event_head; - spinlock_t lock; // for access to event list - unsigned int num_events; - unsigned dropped_event : 1; -}; - -static inline void init_event_queue(struct gpib_event_queue *queue) -{ - INIT_LIST_HEAD(&queue->event_head); - queue->num_events = 0; - queue->dropped_event = 0; - spin_lock_init(&queue->lock); -} - -/* struct for supporting polling operation when irq is not available */ -struct gpib_pseudo_irq { - struct timer_list timer; - irqreturn_t (*handler)(int irq, void *arg); - struct gpib_board *board; - atomic_t active; -}; - -static inline void init_gpib_pseudo_irq(struct gpib_pseudo_irq *pseudo_irq) -{ - pseudo_irq->handler = NULL; - timer_setup(&pseudo_irq->timer, NULL, 0); - atomic_set(&pseudo_irq->active, 0); -} - -/* list so we can make a linked list of drivers */ -struct gpib_interface_list { - struct list_head list; - struct gpib_interface *interface; - struct module *module; -}; - -/* - * One struct gpib_board is allocated for each physical board in the computer. - * It provides storage for variables local to each board, and interface - * functions for performing operations on the board - */ -struct gpib_board { - /* functions used by this board */ - struct gpib_interface *interface; - /* - * Pointer to module whose use count we should increment when - * interface is in use - */ - struct module *provider_module; - /* buffer used to store read/write data for this board */ - u8 *buffer; - /* length of buffer */ - unsigned int buffer_length; - /* - * Used to hold the board's current status (see update_status() above) - */ - unsigned long status; - /* - * Driver should only sleep on this wait queue. It is special in that the - * core will wake this queue and set the TIMO bit in 'status' when the - * watchdog timer times out. - */ - wait_queue_head_t wait; - /* - * Lock that only allows one process to access this board at a time. - * Has to be first in any locking order, since it can be locked over - * multiple ioctls. - */ - struct mutex user_mutex; - /* - * Mutex which compensates for removal of "big kernel lock" from kernel. - * Should not be held for extended waits. - */ - struct mutex big_gpib_mutex; - /* pid of last process to lock the board mutex */ - pid_t locking_pid; - /* lock for setting locking pid */ - spinlock_t locking_pid_spinlock; - /* Spin lock for dealing with races with the interrupt handler */ - spinlock_t spinlock; - /* Watchdog timer to enable timeouts */ - struct timer_list timer; - /* device of attached driver if any */ - struct device *dev; - /* gpib_common device gpibN */ - struct device *gpib_dev; - /* - * 'private_data' can be used as seen fit by the driver to - * store additional variables for this board - */ - void *private_data; - /* Number of open file descriptors using this board */ - unsigned int use_count; - /* list of open devices connected to this board */ - struct list_head device_list; - /* primary address */ - unsigned int pad; - /* secondary address */ - int sad; - /* timeout for io operations, in microseconds */ - unsigned int usec_timeout; - /* board's parallel poll configuration byte */ - u8 parallel_poll_configuration; - /* t1 delay we are using */ - unsigned int t1_nano_sec; - /* Count that keeps track of whether board is up and running or not */ - unsigned int online; - /* number of processes trying to autopoll */ - int autospollers; - /* autospoll kernel thread */ - struct task_struct *autospoll_task; - /* queue for recording received trigger/clear/ifc events */ - struct gpib_event_queue event_queue; - /* minor number for this board's device file */ - int minor; - /* struct to deal with polling mode*/ - struct gpib_pseudo_irq pseudo_irq; - /* error dong autopoll */ - atomic_t stuck_srq; - struct gpib_board_config config; - /* Flag that indicates whether board is system controller of the bus */ - unsigned master : 1; - /* individual status bit */ - unsigned ist : 1; - /* - * one means local parallel poll mode ieee 488.1 PP2 (or no parallel poll PP0), - * zero means remote parallel poll configuration mode ieee 488.1 PP1 - */ - unsigned local_ppoll_mode : 1; -}; - -/* element of event queue */ -struct gpib_event { - struct list_head list; - short event_type; -}; - -/* - * Each board has a list of gpib_status_queue to keep track of all open devices - * on the bus, so we know what address to poll when we get a service request - */ -struct gpib_status_queue { - /* list_head so we can make a linked list of devices */ - struct list_head list; - unsigned int pad; /* primary gpib address */ - int sad; /* secondary gpib address (negative means disabled) */ - /* stores serial poll bytes for this device */ - struct list_head status_bytes; - unsigned int num_status_bytes; - /* number of times this address is opened */ - unsigned int reference_count; - /* flags loss of status byte error due to limit on size of queue */ - unsigned dropped_byte : 1; -}; - -struct gpib_status_byte { - struct list_head list; - u8 poll_byte; -}; - -void init_gpib_status_queue(struct gpib_status_queue *device); - -/* Used to store device-descriptor-specific information */ -struct gpib_descriptor { - unsigned int pad; /* primary gpib address */ - int sad; /* secondary gpib address (negative means disabled) */ - atomic_t io_in_progress; - unsigned is_board : 1; - unsigned autopoll_enabled : 1; -}; - -struct gpib_file_private { - atomic_t holding_mutex; - struct gpib_descriptor *descriptors[GPIB_MAX_NUM_DESCRIPTORS]; - /* locked while descriptors are being allocated/deallocated */ - struct mutex descriptors_mutex; - unsigned got_module : 1; -}; - -#endif /* __KERNEL__ */ - -#endif /* _GPIB_TYPES_H */ diff --git a/drivers/staging/gpib/include/nec7210.h b/drivers/staging/gpib/include/nec7210.h deleted file mode 100644 index 9835aa5ef4ff..000000000000 --- a/drivers/staging/gpib/include/nec7210.h +++ /dev/null @@ -1,141 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _NEC7210_H -#define _NEC7210_H - -#include "gpib_state_machines.h" -#include <linux/types.h> -#include <linux/spinlock.h> -#include <linux/string.h> -#include <linux/interrupt.h> - -#include "gpib_types.h" -#include "nec7210_registers.h" - -/* struct used to provide variables local to a nec7210 chip */ -struct nec7210_priv { -#ifdef CONFIG_HAS_IOPORT - u32 iobase; -#endif - void __iomem *mmiobase; - unsigned int offset; // offset between successive nec7210 io addresses - unsigned int dma_channel; - u8 *dma_buffer; - unsigned int dma_buffer_length; // length of dma buffer - dma_addr_t dma_buffer_addr; // bus address of board->buffer for use with dma - // software copy of bits written to registers - u8 reg_bits[8]; - u8 auxa_bits; // bits written to auxiliary register A - u8 auxb_bits; // bits written to auxiliary register B - // used to keep track of board's state, bit definitions given below - unsigned long state; - // lock for chips that extend the nec7210 registers by paging in alternate regs - spinlock_t register_page_lock; - // wrappers for outb, inb, readb, or writeb - u8 (*read_byte)(struct nec7210_priv *priv, unsigned int register_number); - void (*write_byte)(struct nec7210_priv *priv, u8 byte, unsigned int register_number); - enum nec7210_chipset type; - enum talker_function_state talker_state; - enum listener_function_state listener_state; - void *private; - unsigned srq_pending : 1; -}; - -static inline void init_nec7210_private(struct nec7210_priv *priv) -{ - memset(priv, 0, sizeof(struct nec7210_priv)); - spin_lock_init(&priv->register_page_lock); -} - -// slightly shorter way to access read_byte and write_byte -static inline u8 read_byte(struct nec7210_priv *priv, unsigned int register_number) -{ - return priv->read_byte(priv, register_number); -} - -static inline void write_byte(struct nec7210_priv *priv, u8 byte, unsigned int register_number) -{ - priv->write_byte(priv, byte, register_number); -} - -// struct nec7210_priv.state bit numbers -enum { - PIO_IN_PROGRESS_BN, // pio transfer in progress - DMA_READ_IN_PROGRESS_BN, // dma read transfer in progress - DMA_WRITE_IN_PROGRESS_BN, // dma write transfer in progress - READ_READY_BN, // board has data byte available to read - WRITE_READY_BN, // board is ready to send a data byte - COMMAND_READY_BN, // board is ready to send a command byte - RECEIVED_END_BN, // received END - BUS_ERROR_BN, // output error has occurred - RFD_HOLDOFF_BN, // rfd holdoff in effect - DEV_CLEAR_BN, // device clear received - ADR_CHANGE_BN, // address state change occurred -}; - -// interface functions -int nec7210_read(struct gpib_board *board, struct nec7210_priv *priv, u8 *buffer, - size_t length, int *end, size_t *bytes_read); -int nec7210_write(struct gpib_board *board, struct nec7210_priv *priv, u8 *buffer, - size_t length, int send_eoi, size_t *bytes_written); -int nec7210_command(struct gpib_board *board, struct nec7210_priv *priv, u8 *buffer, - size_t length, size_t *bytes_written); -int nec7210_take_control(struct gpib_board *board, struct nec7210_priv *priv, int syncronous); -int nec7210_go_to_standby(struct gpib_board *board, struct nec7210_priv *priv); -int nec7210_request_system_control(struct gpib_board *board, - struct nec7210_priv *priv, int request_control); -void nec7210_interface_clear(struct gpib_board *board, struct nec7210_priv *priv, int assert); -void nec7210_remote_enable(struct gpib_board *board, struct nec7210_priv *priv, int enable); -int nec7210_enable_eos(struct gpib_board *board, struct nec7210_priv *priv, u8 eos_bytes, - int compare_8_bits); -void nec7210_disable_eos(struct gpib_board *board, struct nec7210_priv *priv); -unsigned int nec7210_update_status(struct gpib_board *board, struct nec7210_priv *priv, - unsigned int clear_mask); -unsigned int nec7210_update_status_nolock(struct gpib_board *board, struct nec7210_priv *priv); -int nec7210_primary_address(const struct gpib_board *board, - struct nec7210_priv *priv, unsigned int address); -int nec7210_secondary_address(const struct gpib_board *board, struct nec7210_priv *priv, - unsigned int address, int enable); -int nec7210_parallel_poll(struct gpib_board *board, struct nec7210_priv *priv, u8 *result); -void nec7210_serial_poll_response(struct gpib_board *board, - struct nec7210_priv *priv, u8 status); -void nec7210_parallel_poll_configure(struct gpib_board *board, - struct nec7210_priv *priv, unsigned int configuration); -void nec7210_parallel_poll_response(struct gpib_board *board, - struct nec7210_priv *priv, int ist); -u8 nec7210_serial_poll_status(struct gpib_board *board, struct nec7210_priv *priv); -int nec7210_t1_delay(struct gpib_board *board, - struct nec7210_priv *priv, unsigned int nano_sec); -void nec7210_return_to_local(const struct gpib_board *board, struct nec7210_priv *priv); - -// utility functions -void nec7210_board_reset(struct nec7210_priv *priv, const struct gpib_board *board); -void nec7210_board_online(struct nec7210_priv *priv, const struct gpib_board *board); -unsigned int nec7210_set_reg_bits(struct nec7210_priv *priv, unsigned int reg, - unsigned int mask, unsigned int bits); -void nec7210_set_handshake_mode(struct gpib_board *board, struct nec7210_priv *priv, int mode); -void nec7210_release_rfd_holdoff(struct gpib_board *board, struct nec7210_priv *priv); -u8 nec7210_read_data_in(struct gpib_board *board, struct nec7210_priv *priv, int *end); - -// wrappers for io functions -u8 nec7210_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num); -void nec7210_ioport_write_byte(struct nec7210_priv *priv, u8 data, unsigned int register_num); -u8 nec7210_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num); -void nec7210_iomem_write_byte(struct nec7210_priv *priv, u8 data, unsigned int register_num); -u8 nec7210_locking_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num); -void nec7210_locking_ioport_write_byte(struct nec7210_priv *priv, u8 data, - unsigned int register_num); -u8 nec7210_locking_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num); -void nec7210_locking_iomem_write_byte(struct nec7210_priv *priv, u8 data, - unsigned int register_num); - -// interrupt service routine -irqreturn_t nec7210_interrupt(struct gpib_board *board, struct nec7210_priv *priv); -irqreturn_t nec7210_interrupt_have_status(struct gpib_board *board, - struct nec7210_priv *priv, int status1, int status2); - -#endif //_NEC7210_H diff --git a/drivers/staging/gpib/include/nec7210_registers.h b/drivers/staging/gpib/include/nec7210_registers.h deleted file mode 100644 index 067983d7a07f..000000000000 --- a/drivers/staging/gpib/include/nec7210_registers.h +++ /dev/null @@ -1,218 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _NEC7210_REGISTERS_H -#define _NEC7210_REGISTERS_H - -enum nec7210_chipset { - NEC7210, // The original - TNT4882, // NI - NAT4882, // NI - CB7210, // measurement computing - IOT7210, // iotech - IGPIB7210, // Ines - TNT5004, // NI (minor differences to TNT4882) -}; - -/* - * nec7210 register numbers (might need to be multiplied by - * a board-dependent offset to get actually io address offset) - */ -// write registers -enum nec7210_write_regs { - CDOR, // command/data out - IMR1, // interrupt mask 1 - IMR2, // interrupt mask 2 - SPMR, // serial poll mode - ADMR, // address mode - AUXMR, // auxiliary mode - ADR, // address - EOSR, // end-of-string - - // nec7210 has 8 registers - nec7210_num_registers = 8, -}; - -// read registers -enum nec7210_read_regs { - DIR, // data in - ISR1, // interrupt status 1 - ISR2, // interrupt status 2 - SPSR, // serial poll status - ADSR, // address status - CPTR, // command pass though - ADR0, // address 1 - ADR1, // address 2 -}; - -// bit definitions common to nec-7210 compatible registers - -// ISR1: interrupt status register 1 -enum isr1_bits { - HR_DI = (1 << 0), - HR_DO = (1 << 1), - HR_ERR = (1 << 2), - HR_DEC = (1 << 3), - HR_END = (1 << 4), - HR_DET = (1 << 5), - HR_APT = (1 << 6), - HR_CPT = (1 << 7), -}; - -// IMR1: interrupt mask register 1 -enum imr1_bits { - HR_DIIE = (1 << 0), - HR_DOIE = (1 << 1), - HR_ERRIE = (1 << 2), - HR_DECIE = (1 << 3), - HR_ENDIE = (1 << 4), - HR_DETIE = (1 << 5), - HR_APTIE = (1 << 6), - HR_CPTIE = (1 << 7), -}; - -// ISR2, interrupt status register 2 -enum isr2_bits { - HR_ADSC = (1 << 0), - HR_REMC = (1 << 1), - HR_LOKC = (1 << 2), - HR_CO = (1 << 3), - HR_REM = (1 << 4), - HR_LOK = (1 << 5), - HR_SRQI = (1 << 6), - HR_INT = (1 << 7), -}; - -// IMR2, interrupt mask register 2 -enum imr2_bits { - // all the bits in this register that enable interrupts - IMR2_ENABLE_INTR_MASK = 0x4f, - HR_ACIE = (1 << 0), - HR_REMIE = (1 << 1), - HR_LOKIE = (1 << 2), - HR_COIE = (1 << 3), - HR_DMAI = (1 << 4), - HR_DMAO = (1 << 5), - HR_SRQIE = (1 << 6), -}; - -// SPSR, serial poll status register -enum spsr_bits { - HR_PEND = (1 << 6), -}; - -// SPMR, serial poll mode register -enum spmr_bits { - HR_RSV = (1 << 6), -}; - -// ADSR, address status register -enum adsr_bits { - HR_MJMN = (1 << 0), - HR_TA = (1 << 1), - HR_LA = (1 << 2), - HR_TPAS = (1 << 3), - HR_LPAS = (1 << 4), - HR_SPMS = (1 << 5), - HR_NATN = (1 << 6), - HR_CIC = (1 << 7), -}; - -// ADMR, address mode register -enum admr_bits { - HR_ADM0 = (1 << 0), - HR_ADM1 = (1 << 1), - HR_TRM0 = (1 << 4), - HR_TRM1 = (1 << 5), - HR_TRM_EOIOE_TRIG = 0, - HR_TRM_CIC_TRIG = HR_TRM0, - HR_TRM_CIC_EOIOE = HR_TRM1, - HR_TRM_CIC_PE = HR_TRM0 | HR_TRM1, - HR_LON = (1 << 6), - HR_TON = (1 << 7), -}; - -// ADR, bits used in address0, address1 and address0/1 registers -enum adr_bits { - ADDRESS_MASK = 0x1f, /* mask to specify lower 5 bits */ - HR_DL = (1 << 5), - HR_DT = (1 << 6), - HR_ARS = (1 << 7), -}; - -// ADR1, address1 register -enum adr1_bits { - HR_EOI = (1 << 7), -}; - -// AUXMR, auxiliary mode register -enum auxmr_bits { - ICR = 0x20, - PPR = 0x60, - AUXRA = 0x80, - AUXRB = 0xa0, - AUXRE = 0xc0, -}; - -// auxra, auxiliary register A -enum auxra_bits { - HR_HANDSHAKE_MASK = 0x3, - HR_HLDA = 0x1, - HR_HLDE = 0x2, - HR_LCM = 0x3, /* auxra listen continuous */ - HR_REOS = 0x4, - HR_XEOS = 0x8, - HR_BIN = 0x10, -}; - -// auxrb, auxiliary register B -enum auxrb_bits { - HR_CPTE = (1 << 0), - HR_SPEOI = (1 << 1), - HR_TRI = (1 << 2), - HR_INV = (1 << 3), - HR_ISS = (1 << 4), -}; - -enum auxre_bits { - HR_DAC_HLD_DCAS = 0x1, /* perform DAC holdoff on receiving clear */ - HR_DAC_HLD_DTAS = 0x2, /* perform DAC holdoff on receiving trigger */ -}; - -// parallel poll register -enum ppr_bits { - HR_PPS = (1 << 3), - HR_PPU = (1 << 4), -}; - -/* 7210 Auxiliary Commands */ -enum aux_cmds { - AUX_PON = 0x0, /* Immediate Execute pon */ - AUX_CPPF = 0x1, /* Clear Parallel Poll Flag */ - AUX_CR = 0x2, /* Chip Reset */ - AUX_FH = 0x3, /* Finish Handshake */ - AUX_TRIG = 0x4, /* Trigger */ - AUX_RTL = 0x5, /* Return to local */ - AUX_SEOI = 0x6, /* Send EOI */ - AUX_NVAL = 0x7, /* Non-Valid Secondary Command or Address */ - AUX_SPPF = 0x9, /* Set Parallel Poll Flag */ - AUX_VAL = 0xf, /* Valid Secondary Command or Address */ - AUX_GTS = 0x10, /* Go To Standby */ - AUX_TCA = 0x11, /* Take Control Asynchronously */ - AUX_TCS = 0x12, /* Take Control Synchronously */ - AUX_LTN = 0x13, /* Listen */ - AUX_DSC = 0x14, /* Disable System Control */ - AUX_CIFC = 0x16, /* Clear IFC */ - AUX_CREN = 0x17, /* Clear REN */ - AUX_TCSE = 0x1a, /* Take Control Synchronously on End */ - AUX_LTNC = 0x1b, /* Listen in Continuous Mode */ - AUX_LUN = 0x1c, /* Local Unlisten */ - AUX_EPP = 0x1d, /* Execute Parallel Poll */ - AUX_SIFC = 0x1e, /* Set IFC */ - AUX_SREN = 0x1f, /* Set REN */ -}; - -#endif //_NEC7210_REGISTERS_H diff --git a/drivers/staging/gpib/include/plx9050.h b/drivers/staging/gpib/include/plx9050.h deleted file mode 100644 index c911b285a0ca..000000000000 --- a/drivers/staging/gpib/include/plx9050.h +++ /dev/null @@ -1,72 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * Header for plx9050 pci chip - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _PLX9050_GPIB_H -#define _PLX9050_GPIB_H - -// plx pci chip registers and bits -enum { - PLX9050_INTCSR_REG = 0x4c, - PLX9050_CNTRL_REG = 0x50 -}; - -enum plx9050_intcsr_bits { - PLX9050_LINTR1_EN_BIT = 0x1, - PLX9050_LINTR1_POLARITY_BIT = 0x2, - PLX9050_LINTR1_STATUS_BIT = 0x4, - PLX9050_LINTR2_EN_BIT = 0x8, - PLX9050_LINTR2_POLARITY_BIT = 0x10, - PLX9050_LINTR2_STATUS_BIT = 0x20, - PLX9050_PCI_INTR_EN_BIT = 0x40, - PLX9050_SOFT_INTR_BIT = 0x80, - PLX9050_LINTR1_SELECT_ENABLE_BIT = 0x100, // 9052 extension - PLX9050_LINTR2_SELECT_ENABLE_BIT = 0x200, // 9052 extension - PLX9050_LINTR1_EDGE_CLEAR_BIT = 0x400, // 9052 extension - PLX9050_LINTR2_EDGE_CLEAR_BIT = 0x800, // 9052 extension -}; - -enum plx9050_cntrl_bits { - PLX9050_WAITO_NOT_USER0_SELECT_BIT = 0x1, - PLX9050_USER0_OUTPUT_BIT = 0x2, - PLX9050_USER0_DATA_BIT = 0x4, - PLX9050_LLOCK_NOT_USER1_SELECT_BIT = 0x8, - PLX9050_USER1_OUTPUT_BIT = 0x10, - PLX9050_USER1_DATA_BIT = 0x20, - PLX9050_CS2_NOT_USER2_SELECT_BIT = 0x40, - PLX9050_USER2_OUTPUT_BIT = 0x80, - PLX9050_USER2_DATA_BIT = 0x100, - PLX9050_CS3_NOT_USER3_SELECT_BIT = 0x200, - PLX9050_USER3_OUTPUT_BIT = 0x400, - PLX9050_USER3_DATA_BIT = 0x800, - PLX9050_PCIBAR_ENABLE_MASK = 0x3000, - PLX9050_PCIBAR_MEMORY_AND_IO_ENABLE_BITS = 0x0, - PLX9050_PCIBAR_MEMORY_NO_IO_ENABLE_BITS = 0x1000, - PLX9050_PCIBAR_IO_NO_MEMORY_ENABLE_BITS = 0x2000, - PLX9050_PCIBAR_MEMORY_AND_IO_TOO_ENABLE_BITS = 0x3000, - PLX9050_PCI_READ_MODE_BIT = 0x4000, - PLX9050_PCI_READ_WITH_WRITE_FLUSH_MODE_BIT = 0x8000, - PLX9050_PCI_READ_NO_FLUSH_MODE_BIT = 0x10000, - PLX9050_PCI_READ_NO_WRITE_MODE_BIT = 0x20000, - PLX9050_PCI_WRITE_MODE_BIT = 0x40000, - PLX9050_PCI_RETRY_DELAY_MASK = 0x780000, - PLX9050_DIRECT_SLAVE_LOCK_ENABLE_BIT = 0x800000, - PLX9050_EEPROM_CLOCK_BIT = 0x1000000, - PLX9050_EEPROM_CHIP_SELECT_BIT = 0x2000000, - PLX9050_WRITE_TO_EEPROM_BIT = 0x4000000, - PLX9050_READ_EEPROM_DATA_BIT = 0x8000000, - PLX9050_EEPROM_VALID_BIT = 0x10000000, - PLX9050_RELOAD_CONFIG_REGISTERS_BIT = 0x20000000, - PLX9050_PCI_SOFTWARE_RESET_BIT = 0x40000000, - PLX9050_MASK_REVISION_BIT = 0x80000000 -}; - -static inline unsigned int PLX9050_PCI_RETRY_DELAY_BITS(unsigned int clocks) -{ - return ((clocks / 8) << 19) & PLX9050_PCI_RETRY_DELAY_MASK; -} - -#endif // _PLX9050_GPIB_H diff --git a/drivers/staging/gpib/include/quancom_pci.h b/drivers/staging/gpib/include/quancom_pci.h deleted file mode 100644 index cdaf0d056be9..000000000000 --- a/drivers/staging/gpib/include/quancom_pci.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * Quancom pci stuff - * copyright (C) 2005 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _QUANCOM_PCI_H -#define _QUANCOM_PCI_H - -/* quancom registers */ -enum quancom_regs { - QUANCOM_IRQ_CONTROL_STATUS_REG = 0xfc, -}; - -enum quancom_irq_control_status_bits { - QUANCOM_IRQ_ASSERTED_BIT = 0x1, /* readable */ - /* (any write to the register clears the interrupt)*/ - QUANCOM_IRQ_ENABLE_BIT = 0x4, /* writeable */ -}; - -#endif // _QUANCOM_PCI_H diff --git a/drivers/staging/gpib/include/tms9914.h b/drivers/staging/gpib/include/tms9914.h deleted file mode 100644 index e66b75e0fda8..000000000000 --- a/drivers/staging/gpib/include/tms9914.h +++ /dev/null @@ -1,280 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _TMS9914_H -#define _TMS9914_H - -#include <linux/types.h> -#include <linux/interrupt.h> -#include "gpib_state_machines.h" -#include "gpib_types.h" - -enum tms9914_holdoff_mode { - TMS9914_HOLDOFF_NONE, - TMS9914_HOLDOFF_EOI, - TMS9914_HOLDOFF_ALL, -}; - -/* struct used to provide variables local to a tms9914 chip */ -struct tms9914_priv { -#ifdef CONFIG_HAS_IOPORT - u32 iobase; -#endif - void __iomem *mmiobase; - unsigned int offset; // offset between successive tms9914 io addresses - unsigned int dma_channel; - // software copy of bits written to interrupt mask registers - u8 imr0_bits, imr1_bits; - // bits written to address mode register - u8 admr_bits; - u8 auxa_bits; // bits written to auxiliary register A - // used to keep track of board's state, bit definitions given below - unsigned long state; - u8 eos; // eos character - short eos_flags; - u8 spoll_status; - enum tms9914_holdoff_mode holdoff_mode; - unsigned int ppoll_line; - enum talker_function_state talker_state; - enum listener_function_state listener_state; - unsigned ppoll_sense : 1; - unsigned ppoll_enable : 1; - unsigned ppoll_configure_state : 1; - unsigned primary_listen_addressed : 1; - unsigned primary_talk_addressed : 1; - unsigned holdoff_on_end : 1; - unsigned holdoff_on_all : 1; - unsigned holdoff_active : 1; - // wrappers for outb, inb, readb, or writeb - u8 (*read_byte)(struct tms9914_priv *priv, unsigned int register_number); - void (*write_byte)(struct tms9914_priv *priv, u8 byte, unsigned int - register_number); -}; - -// slightly shorter way to access read_byte and write_byte -static inline u8 read_byte(struct tms9914_priv *priv, unsigned int register_number) -{ - return priv->read_byte(priv, register_number); -} - -static inline void write_byte(struct tms9914_priv *priv, u8 byte, unsigned int register_number) -{ - priv->write_byte(priv, byte, register_number); -} - -// struct tms9914_priv.state bit numbers -enum { - PIO_IN_PROGRESS_BN, // pio transfer in progress - DMA_READ_IN_PROGRESS_BN, // dma read transfer in progress - DMA_WRITE_IN_PROGRESS_BN, // dma write transfer in progress - READ_READY_BN, // board has data byte available to read - WRITE_READY_BN, // board is ready to send a data byte - COMMAND_READY_BN, // board is ready to send a command byte - RECEIVED_END_BN, // received END - BUS_ERROR_BN, // bus error - DEV_CLEAR_BN, // device clear received -}; - -// interface functions -int tms9914_read(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, - size_t length, int *end, size_t *bytes_read); -int tms9914_write(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, - size_t length, int send_eoi, size_t *bytes_written); -int tms9914_command(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, - size_t length, size_t *bytes_written); -int tms9914_take_control(struct gpib_board *board, struct tms9914_priv *priv, int syncronous); -/* - * alternate version of tms9914_take_control which works around buggy tcs - * implementation. - */ -int tms9914_take_control_workaround(struct gpib_board *board, struct tms9914_priv *priv, - int syncronous); -int tms9914_go_to_standby(struct gpib_board *board, struct tms9914_priv *priv); -int tms9914_request_system_control(struct gpib_board *board, struct tms9914_priv *priv, - int request_control); -void tms9914_interface_clear(struct gpib_board *board, struct tms9914_priv *priv, int assert); -void tms9914_remote_enable(struct gpib_board *board, struct tms9914_priv *priv, int enable); -int tms9914_enable_eos(struct gpib_board *board, struct tms9914_priv *priv, u8 eos_bytes, - int compare_8_bits); -void tms9914_disable_eos(struct gpib_board *board, struct tms9914_priv *priv); -unsigned int tms9914_update_status(struct gpib_board *board, struct tms9914_priv *priv, - unsigned int clear_mask); -int tms9914_primary_address(struct gpib_board *board, - struct tms9914_priv *priv, unsigned int address); -int tms9914_secondary_address(struct gpib_board *board, struct tms9914_priv *priv, - unsigned int address, int enable); -int tms9914_parallel_poll(struct gpib_board *board, struct tms9914_priv *priv, u8 *result); -void tms9914_parallel_poll_configure(struct gpib_board *board, - struct tms9914_priv *priv, u8 config); -void tms9914_parallel_poll_response(struct gpib_board *board, - struct tms9914_priv *priv, int ist); -void tms9914_serial_poll_response(struct gpib_board *board, - struct tms9914_priv *priv, u8 status); -u8 tms9914_serial_poll_status(struct gpib_board *board, struct tms9914_priv *priv); -int tms9914_line_status(const struct gpib_board *board, struct tms9914_priv *priv); -unsigned int tms9914_t1_delay(struct gpib_board *board, struct tms9914_priv *priv, - unsigned int nano_sec); -void tms9914_return_to_local(const struct gpib_board *board, struct tms9914_priv *priv); - -// utility functions -void tms9914_board_reset(struct tms9914_priv *priv); -void tms9914_online(struct gpib_board *board, struct tms9914_priv *priv); -void tms9914_release_holdoff(struct tms9914_priv *priv); -void tms9914_set_holdoff_mode(struct tms9914_priv *priv, enum tms9914_holdoff_mode mode); - -// wrappers for io functions -u8 tms9914_ioport_read_byte(struct tms9914_priv *priv, unsigned int register_num); -void tms9914_ioport_write_byte(struct tms9914_priv *priv, u8 data, unsigned int register_num); -u8 tms9914_iomem_read_byte(struct tms9914_priv *priv, unsigned int register_num); -void tms9914_iomem_write_byte(struct tms9914_priv *priv, u8 data, unsigned int register_num); - -// interrupt service routine -irqreturn_t tms9914_interrupt(struct gpib_board *board, struct tms9914_priv *priv); -irqreturn_t tms9914_interrupt_have_status(struct gpib_board *board, struct tms9914_priv *priv, - int status1, int status2); - -// tms9914 has 8 registers -enum { - ms9914_num_registers = 8, -}; - -/* - * tms9914 register numbers (might need to be multiplied by - * a board-dependent offset to get actually io address offset) - */ -// write registers -enum { - IMR0 = 0, /* interrupt mask 0 */ - IMR1 = 1, /* interrupt mask 1 */ - AUXCR = 3, /* auxiliary command */ - ADR = 4, /* address register */ - SPMR = 5, /* serial poll mode register */ - PPR = 6, /* parallel poll */ - CDOR = 7, /* data out register */ -}; - -// read registers -enum { - ISR0 = 0, /* interrupt status 0 */ - ISR1 = 1, /* interrupt status 1 */ - ADSR = 2, /* address status */ - BSR = 3, /* bus status */ - CPTR = 6, /* command pass thru */ - DIR = 7, /* data in register */ -}; - -// bit definitions common to tms9914 compatible registers - -/* ISR0 - Register bits */ -enum isr0_bits { - HR_MAC = (1 << 0), /* My Address Change */ - HR_RLC = (1 << 1), /* Remote/Local change */ - HR_SPAS = (1 << 2), /* Serial Poll active State */ - HR_END = (1 << 3), /* END (EOI or EOS) */ - HR_BO = (1 << 4), /* Byte Out */ - HR_BI = (1 << 5), /* Byte In */ -}; - -/* IMR0 - Register bits */ -enum imr0_bits { - HR_MACIE = (1 << 0), /* */ - HR_RLCIE = (1 << 1), /* */ - HR_SPASIE = (1 << 2), /* */ - HR_ENDIE = (1 << 3), /* */ - HR_BOIE = (1 << 4), /* */ - HR_BIIE = (1 << 5), /* */ -}; - -/* ISR1 - Register bits */ -enum isr1_bits { - HR_IFC = (1 << 0), /* IFC asserted */ - HR_SRQ = (1 << 1), /* SRQ asserted */ - HR_MA = (1 << 2), /* My Address */ - HR_DCAS = (1 << 3), /* Device Clear active State */ - HR_APT = (1 << 4), /* Address pass Through */ - HR_UNC = (1 << 5), /* Unrecognized Command */ - HR_ERR = (1 << 6), /* Data Transmission Error */ - HR_GET = (1 << 7), /* Group execute Trigger */ -}; - -/* IMR1 - Register bits */ -enum imr1_bits { - HR_IFCIE = (1 << 0), /* */ - HR_SRQIE = (1 << 1), /* */ - HR_MAIE = (1 << 2), /* */ - HR_DCASIE = (1 << 3), /* */ - HR_APTIE = (1 << 4), /* */ - HR_UNCIE = (1 << 5), /* */ - HR_ERRIE = (1 << 6), /* */ - HR_GETIE = (1 << 7), /* */ -}; - -/* ADSR - Register bits */ -enum adsr_bits { - HR_ULPA = (1 << 0), /* Store last address LSB */ - HR_TA = (1 << 1), /* Talker Adressed */ - HR_LA = (1 << 2), /* Listener adressed */ - HR_TPAS = (1 << 3), /* talker primary address state */ - HR_LPAS = (1 << 4), /* listener " */ - HR_ATN = (1 << 5), /* ATN active */ - HR_LLO = (1 << 6), /* LLO active */ - HR_REM = (1 << 7), /* REM active */ -}; - -/* ADR - Register bits */ -enum adr_bits { - ADDRESS_MASK = 0x1f, /* mask to specify lower 5 bits for ADR */ - HR_DAT = (1 << 5), /* disable talker */ - HR_DAL = (1 << 6), /* disable listener */ - HR_EDPA = (1 << 7), /* enable dual primary addressing */ -}; - -enum bus_status_bits { - BSR_REN_BIT = 0x1, - BSR_IFC_BIT = 0x2, - BSR_SRQ_BIT = 0x4, - BSR_EOI_BIT = 0x8, - BSR_NRFD_BIT = 0x10, - BSR_NDAC_BIT = 0x20, - BSR_DAV_BIT = 0x40, - BSR_ATN_BIT = 0x80, -}; - -/*---------------------------------------------------------*/ -/* TMS 9914 Auxiliary Commands */ -/*---------------------------------------------------------*/ - -enum aux_cmd_bits { - AUX_CS = 0x80, /* set bit instead of clearing it, used with commands marked 'd' below */ - AUX_CHIP_RESET = 0x0, /* d Chip reset */ - AUX_INVAL = 0x1, /* release dac holdoff, invalid command byte */ - AUX_VAL = (AUX_INVAL | AUX_CS), /* release dac holdoff, valid command byte */ - AUX_RHDF = 0x2, /* X Release RFD holdoff */ - AUX_HLDA = 0x3, /* d holdoff on all data */ - AUX_HLDE = 0x4, /* d holdoff on EOI only */ - AUX_NBAF = 0x5, /* X Set new byte available false */ - AUX_FGET = 0x6, /* d force GET */ - AUX_RTL = 0x7, /* d return to local */ - AUX_SEOI = 0x8, /* X send EOI with next byte */ - AUX_LON = 0x9, /* d Listen only */ - AUX_TON = 0xa, /* d Talk only */ - AUX_GTS = 0xb, /* X goto standby */ - AUX_TCA = 0xc, /* X take control asynchronously */ - AUX_TCS = 0xd, /* X take " synchronously */ - AUX_RPP = 0xe, /* d Request parallel poll */ - AUX_SIC = 0xf, /* d send interface clear */ - AUX_SRE = 0x10, /* d send remote enable */ - AUX_RQC = 0x11, /* X request control */ - AUX_RLC = 0x12, /* X release control */ - AUX_DAI = 0x13, /* d disable all interrupts */ - AUX_PTS = 0x14, /* X pass through next secondary */ - AUX_STDL = 0x15, /* d short T1 delay */ - AUX_SHDW = 0x16, /* d shadow handshake */ - AUX_VSTDL = 0x17, /* d very short T1 delay (smj9914 extension) */ - AUX_RSV2 = 0x18, /* d request service bit 2 (smj9914 extension) */ -}; - -#endif //_TMS9914_H diff --git a/drivers/staging/gpib/include/tnt4882_registers.h b/drivers/staging/gpib/include/tnt4882_registers.h deleted file mode 100644 index d54c4cc61168..000000000000 --- a/drivers/staging/gpib/include/tnt4882_registers.h +++ /dev/null @@ -1,192 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002, 2004 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _TNT4882_REGISTERS_H -#define _TNT4882_REGISTERS_H - -// tnt4882 register offsets -enum { - ACCWR = 0x5, - // offset of auxiliary command register in 9914 mode - AUXCR = 0x6, - INTRT = 0x7, - // register number for auxiliary command register when swap bit is set (9914 mode) - SWAPPED_AUXCR = 0xa, - HSSEL = 0xd, // handshake select register - CNT2 = 0x9, - CNT3 = 0xb, - CFG = 0x10, - SASR = 0x1b, - IMR0 = 0x1d, - IMR3 = 0x12, - CNT0 = 0x14, - CNT1 = 0x16, - KEYREG = 0x17, // key control register (7210 mode only) - CSR = KEYREG, - FIFOB = 0x18, - FIFOA = 0x19, - CCR = 0x1a, // carry cycle register - CMDR = 0x1c, // command register - TIMER = 0x1e, // timer register - - STS1 = 0x10, // T488 Status Register 1 - STS2 = 0x1c, // T488 Status Register 2 - ISR0 = IMR0, - ISR3 = 0x1a, // T488 Interrupt Status Register 3 - BCR = 0x1f, // bus control/status register - BSR = BCR, -}; - -enum { - tnt_pagein_offset = 0x11, -}; - -/*============================================================*/ - -/* TURBO-488 registers bit definitions */ - -enum bus_control_status_bits { - BCSR_REN_BIT = 0x1, - BCSR_IFC_BIT = 0x2, - BCSR_SRQ_BIT = 0x4, - BCSR_EOI_BIT = 0x8, - BCSR_NRFD_BIT = 0x10, - BCSR_NDAC_BIT = 0x20, - BCSR_DAV_BIT = 0x40, - BCSR_ATN_BIT = 0x80, -}; - -/* CFG -- Configuration Register (write only) */ -enum cfg_bits { - TNT_COMMAND = 0x80, /* bytes are command bytes instead of data bytes - * (tnt4882 one-chip and newer only?) - */ - TNT_TLCHE = (1 << 6), /* halt transfer on imr0, imr1, or imr2 interrupt */ - TNT_IN = (1 << 5), /* transfer is GPIB read */ - TNT_A_B = (1 << 4), /* order to use fifos 1=fifo A first(big endian), - * 0=fifo b first(little endian) - */ - TNT_CCEN = (1 << 3), /* enable carry cycle */ - TNT_TMOE = (1 << 2), /* enable CPU bus time limit */ - TNT_TIM_BYTN = (1 << 1), /* tmot reg is: 1=125ns clocks, 0=num bytes */ - TNT_B_16BIT = (1 << 0), /* 1=FIFO is 16-bit register, 0=8-bit */ -}; - -/* CMDR -- Command Register */ -enum cmdr_bits { - CLRSC = 0x2, /* clear the system controller bit */ - SETSC = 0x3, /* set the system controller bit */ - GO = 0x4, /* start fifos */ - STOP = 0x8, /* stop fifos */ - RESET_FIFO = 0x10, /* reset the FIFOs */ - SOFT_RESET = 0x22, /* issue a software reset */ - HARD_RESET = 0x40 /* 500x only? */ -}; - -/* HSSEL -- handshake select register (write only) */ -enum hssel_bits { - TNT_ONE_CHIP_BIT = 0x1, - NODMA = 0x10, - TNT_GO2SIDS_BIT = 0x20, -}; - -/* IMR0 -- Interrupt Mode Register 0 */ -enum imr0_bits { - TNT_SYNCIE_BIT = 0x1, /* handshake sync */ - TNT_TOIE_BIT = 0x2, /* timeout */ - TNT_ATNIE_BIT = 0x4, /* ATN interrupt */ - TNT_IFCIE_BIT = 0x8, /* interface clear interrupt */ - TNT_BTO_BIT = 0x10, /* byte timeout */ - TNT_NLEN_BIT = 0x20, /* treat new line as EOS char */ - TNT_STBOIE_BIT = 0x40, /* status byte out */ - TNT_IMR0_ALWAYS_BITS = 0x80, /* always set this bit on write */ -}; - -/* ISR0 -- Interrupt Status Register 0 */ -enum isr0_bits { - TNT_SYNC_BIT = 0x1, /* handshake sync */ - TNT_TO_BIT = 0x2, /* timeout */ - TNT_ATNI_BIT = 0x4, /* ATN interrupt */ - TNT_IFCI_BIT = 0x8, /* interface clear interrupt */ - TNT_EOS_BIT = 0x10, /* end of string */ - TNT_NL_BIT = 0x20, /* new line receive */ - TNT_STBO_BIT = 0x40, /* status byte out */ - TNT_NBA_BIT = 0x80, /* new byte available */ -}; - -/* ISR3 -- Interrupt Status Register 3 (read only) */ -enum isr3_bits { - HR_DONE = (1 << 0), /* transfer done */ - HR_TLCI = (1 << 1), /* isr0, isr1, or isr2 interrupt asserted */ - HR_NEF = (1 << 2), /* NOT empty fifo */ - HR_NFF = (1 << 3), /* NOT full fifo */ - HR_STOP = (1 << 4), /* fifo empty or STOP command issued */ - HR_SRQI_CIC = (1 << 5), /* SRQ asserted and we are CIC (500x only?)*/ - HR_INTR = (1 << 7), /* isr3 interrupt active */ -}; - -enum keyreg_bits { - MSTD = 0x20, /* enable 350ns T1 delay */ -}; - -/* STS1 -- Status Register 1 (read only) */ -enum sts1_bits { - S_DONE = 0x80, /* DMA done */ - S_SC = 0x40, /* is system controller */ - S_IN = 0x20, /* DMA in (to memory) */ - S_DRQ = 0x10, /* DRQ line (for diagnostics) */ - S_STOP = 0x08, /* DMA stopped */ - S_NDAV = 0x04, /* inverse of DAV */ - S_HALT = 0x02, /* status of transfer machine */ - S_GSYNC = 0x01, /* indicates if GPIB is in sync w I/O */ -}; - -/* STS2 -- Status Register 2 */ -enum sts2_bits { - AFFN = (1 << 3), /* "A full FIFO NOT" (0=FIFO full) */ - AEFN = (1 << 2), /* "A empty FIFO NOT" (0=FIFO empty) */ - BFFN = (1 << 1), /* "B full FIFO NOT" (0=FIFO full) */ - BEFN = (1 << 0), /* "B empty FIFO NOT" (0=FIFO empty) */ -}; - -// Auxiliary commands -enum tnt4882_aux_cmds { - AUX_9914 = 0x15, // switch to 9914 mode - AUX_REQT = 0x18, - AUX_REQF = 0x19, - AUX_PAGEIN = 0x50, // page in alternate registers - AUX_HLDI = 0x51, // rfd holdoff immediately - AUX_CLEAR_END = 0x55, - AUX_7210 = 0x99, // switch to 7210 mode -}; - -enum tnt4882_aux_regs { - AUXRG = 0x40, - AUXRI = 0xe0, -}; - -enum auxg_bits { - /* no talking when no listeners bit (prevents bus errors when data written at wrong time) */ - NTNL_BIT = 0x8, - RPP2_BIT = 0x4, /* set/clear local rpp message */ - CHES_BIT = 0x1, /*clear holdoff on end select bit*/ -}; - -enum auxi_bits { - SISB = 0x1, // static interrupt bits (don't clear isr1, isr2 on read) - PP2 = 0x4, // ignore remote parallel poll configuration - USTD = 0x8, // ultra short (1100 nanosec) T1 delay -}; - -enum sasr_bits { - ACRDY_BIT = 0x4, /* acceptor ready state */ - ADHS_BIT = 0x8, /* acceptor data holdoff state */ - ANHS2_BIT = 0x10, /* acceptor not ready holdoff immediately state */ - ANHS1_BIT = 0x20, /* acceptor not ready holdoff state */ - AEHS_BIT = 0x40, /* acceptor end holdoff state */ -}; - -#endif // _TNT4882_REGISTERS_H diff --git a/drivers/staging/gpib/ines/Makefile b/drivers/staging/gpib/ines/Makefile deleted file mode 100644 index 88241f15ecea..000000000000 --- a/drivers/staging/gpib/ines/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_GPIB_INES) += ines_gpib.o - - diff --git a/drivers/staging/gpib/ines/ines.h b/drivers/staging/gpib/ines/ines.h deleted file mode 100644 index 6ad57e9a1216..000000000000 --- a/drivers/staging/gpib/ines/ines.h +++ /dev/null @@ -1,165 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * Header for ines GPIB boards - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _INES_GPIB_H -#define _INES_GPIB_H - -#include "nec7210.h" -#include "gpibP.h" -#include "plx9050.h" -#include "amcc5920.h" -#include "quancom_pci.h" -#include <linux/interrupt.h> - -enum ines_pci_chip { - PCI_CHIP_NONE, - PCI_CHIP_PLX9050, - PCI_CHIP_AMCC5920, - PCI_CHIP_QUANCOM, - PCI_CHIP_QUICKLOGIC5030, -}; - -struct ines_priv { - struct nec7210_priv nec7210_priv; - struct pci_dev *pci_device; - // base address for plx9052 pci chip - unsigned long plx_iobase; - // base address for amcc5920 pci chip - unsigned long amcc_iobase; - unsigned int irq; - enum ines_pci_chip pci_chip_type; - u8 extend_mode_bits; -}; - -/* inb/outb wrappers */ -static inline unsigned int ines_inb(struct ines_priv *priv, unsigned int register_number) -{ - return inb(priv->nec7210_priv.iobase + - register_number * priv->nec7210_priv.offset); -} - -static inline void ines_outb(struct ines_priv *priv, unsigned int value, - unsigned int register_number) -{ - outb(value, priv->nec7210_priv.iobase + - register_number * priv->nec7210_priv.offset); -} - -enum ines_regs { - // read - FIFO_STATUS = 0x8, - ISR3 = 0x9, - ISR4 = 0xa, - IN_FIFO_COUNT = 0x10, - OUT_FIFO_COUNT = 0x11, - EXTEND_STATUS = 0xf, - - // write - XDMA_CONTROL = 0x8, - IMR3 = ISR3, - IMR4 = ISR4, - IN_FIFO_WATERMARK = IN_FIFO_COUNT, - OUT_FIFO_WATERMARK = OUT_FIFO_COUNT, - EXTEND_MODE = 0xf, - - // read-write - XFER_COUNT_LOWER = 0xb, - XFER_COUNT_UPPER = 0xc, - BUS_CONTROL_MONITOR = 0x13, -}; - -enum isr3_imr3_bits { - HW_TIMEOUT_BIT = 0x1, - XFER_COUNT_BIT = 0x2, - CMD_RECEIVED_BIT = 0x4, - TCT_RECEIVED_BIT = 0x8, - IFC_ACTIVE_BIT = 0x10, - ATN_ACTIVE_BIT = 0x20, - FIFO_ERROR_BIT = 0x40, -}; - -enum isr4_imr4_bits { - IN_FIFO_WATERMARK_BIT = 0x1, - OUT_FIFO_WATERMARK_BIT = 0x2, - IN_FIFO_FULL_BIT = 0x4, - OUT_FIFO_EMPTY_BIT = 0x8, - IN_FIFO_READY_BIT = 0x10, - OUT_FIFO_READY_BIT = 0x20, - IN_FIFO_EXIT_WATERMARK_BIT = 0x40, - OUT_FIFO_EXIT_WATERMARK_BIT = 0x80, -}; - -enum extend_mode_bits { - TR3_TRIG_ENABLE_BIT = 0x1, // enable generation of trigger pulse T/R3 pin - // clear message available status bit when chip writes byte with EOI true - MAV_ENABLE_BIT = 0x2, - EOS1_ENABLE_BIT = 0x4, // enable eos register 1 - EOS2_ENABLE_BIT = 0x8, // enable eos register 2 - EOIDIS_BIT = 0x10, // disable EOI interrupt when doing rfd holdoff on end? - XFER_COUNTER_ENABLE_BIT = 0x20, - XFER_COUNTER_OUTPUT_BIT = 0x40, // use counter for output, clear for input - // when xfer counter hits 0, assert EOI on write or RFD holdoff on read - LAST_BYTE_HANDLING_BIT = 0x80, -}; - -enum extend_status_bits { - OUTPUT_MESSAGE_IN_PROGRESS_BIT = 0x1, - SCSEL_BIT = 0x2, // statue of SCSEL pin - LISTEN_DISABLED = 0x4, - IN_FIFO_EMPTY_BIT = 0x8, - OUT_FIFO_FULL_BIT = 0x10, -}; - -// ines adds fifo enable bits to address mode register -enum ines_admr_bits { - IN_FIFO_ENABLE_BIT = 0x8, - OUT_FIFO_ENABLE_BIT = 0x4, -}; - -enum xdma_control_bits { - DMA_OUTPUT_BIT = 0x1, // use dma for output, clear for input - ENABLE_SYNC_DMA_BIT = 0x2, - DMA_ACCESS_EVERY_CYCLE = 0x4, // dma accesses fifo every cycle, clear for every other cycle - DMA_16BIT = 0x8, // clear for 8 bit transfers -}; - -enum bus_control_monitor_bits { - BCM_DAV_BIT = 0x1, - BCM_NRFD_BIT = 0x2, - BCM_NDAC_BIT = 0x4, - BCM_IFC_BIT = 0x8, - BCM_ATN_BIT = 0x10, - BCM_SRQ_BIT = 0x20, - BCM_REN_BIT = 0x40, - BCM_EOI_BIT = 0x80, -}; - -enum ines_aux_reg_bits { - INES_AUXD = 0x40, -}; - -enum ines_aux_cmds { - INES_RFD_HLD_IMMEDIATE = 0x4, - INES_AUX_CLR_OUT_FIFO = 0x5, - INES_AUX_CLR_IN_FIFO = 0x6, - INES_AUX_XMODE = 0xa, -}; - -enum ines_auxd_bits { - INES_FOLLOWING_T1_MASK = 0x3, - INES_FOLLOWING_T1_500ns = 0x0, - INES_FOLLOWING_T1_350ns = 0x1, - INES_FOLLOWING_T1_250ns = 0x2, - INES_INITIAL_TI_MASK = 0xc, - INES_INITIAL_T1_2000ns = 0x0, - INES_INITIAL_T1_1100ns = 0x4, - INES_INITIAL_T1_700ns = 0x8, - INES_T6_2us = 0x0, - INES_T6_50us = 0x10, -}; - -#endif // _INES_GPIB_H diff --git a/drivers/staging/gpib/ines/ines_gpib.c b/drivers/staging/gpib/ines/ines_gpib.c deleted file mode 100644 index a3cf846fd0f9..000000000000 --- a/drivers/staging/gpib/ines/ines_gpib.c +++ /dev/null @@ -1,1500 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * copyright : (C) 1999 Axel Dziemba (axel.dziemba@ines.de) - * (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define DRV_NAME KBUILD_MODNAME - -#include "ines.h" - -#include <linux/pci.h> -#include <linux/pci_ids.h> -#include <linux/bitops.h> -#include <asm/dma.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include "gpib_pci_ids.h" - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB driver for Ines iGPIB 72010"); - -static irqreturn_t ines_interrupt(struct gpib_board *board); - -static int ines_line_status(const struct gpib_board *board) -{ - int status = VALID_ALL; - int bcm_bits; - struct ines_priv *ines_priv; - - ines_priv = board->private_data; - - bcm_bits = ines_inb(ines_priv, BUS_CONTROL_MONITOR); - - if (bcm_bits & BCM_REN_BIT) - status |= BUS_REN; - if (bcm_bits & BCM_IFC_BIT) - status |= BUS_IFC; - if (bcm_bits & BCM_SRQ_BIT) - status |= BUS_SRQ; - if (bcm_bits & BCM_EOI_BIT) - status |= BUS_EOI; - if (bcm_bits & BCM_NRFD_BIT) - status |= BUS_NRFD; - if (bcm_bits & BCM_NDAC_BIT) - status |= BUS_NDAC; - if (bcm_bits & BCM_DAV_BIT) - status |= BUS_DAV; - if (bcm_bits & BCM_ATN_BIT) - status |= BUS_ATN; - - return status; -} - -static void ines_set_xfer_counter(struct ines_priv *priv, unsigned int count) -{ - if (count > 0xffff) { - pr_err("bug! tried to set xfer counter > 0xffff\n"); - return; - } - ines_outb(priv, (count >> 8) & 0xff, XFER_COUNT_UPPER); - ines_outb(priv, count & 0xff, XFER_COUNT_LOWER); -} - -static int ines_t1_delay(struct gpib_board *board, unsigned int nano_sec) -{ - struct ines_priv *ines_priv = board->private_data; - struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; - unsigned int retval; - - retval = nec7210_t1_delay(board, nec_priv, nano_sec); - - if (nano_sec <= 250) { - write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_250ns | - INES_INITIAL_T1_2000ns, AUXMR); - retval = 250; - } else if (nano_sec <= 350) { - write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_350ns | - INES_INITIAL_T1_2000ns, AUXMR); - retval = 350; - } else { - write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_500ns | - INES_INITIAL_T1_2000ns, AUXMR); - retval = 500; - } - - return retval; -} - -static inline unsigned short num_in_fifo_bytes(struct ines_priv *ines_priv) -{ - return ines_inb(ines_priv, IN_FIFO_COUNT); -} - -static ssize_t pio_read(struct gpib_board *board, struct ines_priv *ines_priv, u8 *buffer, - size_t length, size_t *nbytes) -{ - ssize_t retval = 0; - unsigned int num_fifo_bytes, i; - struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; - - *nbytes = 0; - while (*nbytes < length) { - if (wait_event_interruptible(board->wait, - num_in_fifo_bytes(ines_priv) || - test_bit(RECEIVED_END_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) - return -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - return -ETIMEDOUT; - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) - return -EINTR; - - num_fifo_bytes = num_in_fifo_bytes(ines_priv); - if (num_fifo_bytes + *nbytes > length) - num_fifo_bytes = length - *nbytes; - - for (i = 0; i < num_fifo_bytes; i++) - buffer[(*nbytes)++] = read_byte(nec_priv, DIR); - if (test_bit(RECEIVED_END_BN, &nec_priv->state) && - num_in_fifo_bytes(ines_priv) == 0) - break; - if (need_resched()) - schedule(); - } - /* make sure RECEIVED_END is in sync */ - ines_interrupt(board); - return retval; -} - -static int ines_accel_read(struct gpib_board *board, u8 *buffer, - size_t length, int *end, size_t *bytes_read) -{ - ssize_t retval = 0; - struct ines_priv *ines_priv = board->private_data; - struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; - int counter_setting; - - *end = 0; - *bytes_read = 0; - if (length == 0) - return 0; - - clear_bit(DEV_CLEAR_BN, &nec_priv->state); - - write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR); - - // clear in fifo - nec7210_set_reg_bits(nec_priv, ADMR, IN_FIFO_ENABLE_BIT, 0); - nec7210_set_reg_bits(nec_priv, ADMR, IN_FIFO_ENABLE_BIT, IN_FIFO_ENABLE_BIT); - - ines_priv->extend_mode_bits |= LAST_BYTE_HANDLING_BIT; - ines_priv->extend_mode_bits &= ~XFER_COUNTER_OUTPUT_BIT & ~XFER_COUNTER_ENABLE_BIT; - ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); - - counter_setting = length - num_in_fifo_bytes(ines_priv); - if (counter_setting > 0) { - ines_set_xfer_counter(ines_priv, length); - ines_priv->extend_mode_bits |= XFER_COUNTER_ENABLE_BIT; - ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); - - // holdoff on END - nec7210_set_handshake_mode(board, nec_priv, HR_HLDE); - /* release rfd holdoff */ - write_byte(nec_priv, AUX_FH, AUXMR); - } - - retval = pio_read(board, ines_priv, buffer, length, bytes_read); - ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT; - ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); - if (retval < 0) { - write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR); - return retval; - } - if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state)) - *end = 1; - - return retval; -} - -static const int out_fifo_size = 0xff; - -static inline unsigned short num_out_fifo_bytes(struct ines_priv *ines_priv) -{ - return ines_inb(ines_priv, OUT_FIFO_COUNT); -} - -static int ines_write_wait(struct gpib_board *board, struct ines_priv *ines_priv, - unsigned int fifo_threshold) -{ - struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; - - // wait until byte is ready to be sent - if (wait_event_interruptible(board->wait, - num_out_fifo_bytes(ines_priv) < fifo_threshold || - test_bit(BUS_ERROR_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) - return -ERESTARTSYS; - - if (test_bit(BUS_ERROR_BN, &nec_priv->state)) - return -EIO; - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) - return -EINTR; - if (test_bit(TIMO_NUM, &board->status)) - return -ETIMEDOUT; - - return 0; -} - -static int ines_accel_write(struct gpib_board *board, u8 *buffer, size_t length, - int send_eoi, size_t *bytes_written) -{ - size_t count = 0; - ssize_t retval = 0; - struct ines_priv *ines_priv = board->private_data; - struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; - unsigned int num_bytes, i; - - *bytes_written = 0; - // clear out fifo - nec7210_set_reg_bits(nec_priv, ADMR, OUT_FIFO_ENABLE_BIT, 0); - nec7210_set_reg_bits(nec_priv, ADMR, OUT_FIFO_ENABLE_BIT, OUT_FIFO_ENABLE_BIT); - - ines_priv->extend_mode_bits |= XFER_COUNTER_OUTPUT_BIT; - ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT; - ines_priv->extend_mode_bits &= ~LAST_BYTE_HANDLING_BIT; - ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); - - ines_set_xfer_counter(ines_priv, length); - if (send_eoi) - ines_priv->extend_mode_bits |= LAST_BYTE_HANDLING_BIT; - ines_priv->extend_mode_bits |= XFER_COUNTER_ENABLE_BIT; - ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); - - while (count < length) { - retval = ines_write_wait(board, ines_priv, out_fifo_size); - if (retval < 0) - break; - - num_bytes = out_fifo_size - num_out_fifo_bytes(ines_priv); - if (num_bytes + count > length) - num_bytes = length - count; - for (i = 0; i < num_bytes; i++) - write_byte(nec_priv, buffer[count++], CDOR); - } - if (retval < 0) { - ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT; - ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); - *bytes_written = length - num_out_fifo_bytes(ines_priv); - return retval; - } - // wait last byte has been sent - retval = ines_write_wait(board, ines_priv, 1); - ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT; - ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); - *bytes_written = length - num_out_fifo_bytes(ines_priv); - - return retval; -} - -static irqreturn_t ines_pci_interrupt(int irq, void *arg) -{ - struct gpib_board *board = arg; - struct ines_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - - if (priv->pci_chip_type == PCI_CHIP_QUANCOM) { - if ((inb(nec_priv->iobase + - QUANCOM_IRQ_CONTROL_STATUS_REG) & - QUANCOM_IRQ_ASSERTED_BIT)) - outb(QUANCOM_IRQ_ENABLE_BIT, nec_priv->iobase + - QUANCOM_IRQ_CONTROL_STATUS_REG); - } - - return ines_interrupt(board); -} - -static irqreturn_t ines_interrupt(struct gpib_board *board) -{ - struct ines_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - unsigned int isr3_bits, isr4_bits; - unsigned long flags; - int wake = 0; - - spin_lock_irqsave(&board->spinlock, flags); - - nec7210_interrupt(board, nec_priv); - isr3_bits = ines_inb(priv, ISR3); - isr4_bits = ines_inb(priv, ISR4); - if (isr3_bits & IFC_ACTIVE_BIT) { - push_gpib_event(board, EVENT_IFC); - wake++; - } - if (isr3_bits & FIFO_ERROR_BIT) - dev_err(board->gpib_dev, "fifo error\n"); - if (isr3_bits & XFER_COUNT_BIT) - wake++; - - if (isr4_bits & (IN_FIFO_WATERMARK_BIT | IN_FIFO_FULL_BIT | OUT_FIFO_WATERMARK_BIT | - OUT_FIFO_EMPTY_BIT)) - wake++; - - if (wake) - wake_up_interruptible(&board->wait); - spin_unlock_irqrestore(&board->spinlock, flags); - return IRQ_HANDLED; -} - -static int ines_pci_attach(struct gpib_board *board, const struct gpib_board_config *config); -static int ines_pci_accel_attach(struct gpib_board *board, const struct gpib_board_config *config); -static int ines_isa_attach(struct gpib_board *board, const struct gpib_board_config *config); - -static void ines_pci_detach(struct gpib_board *board); -static void ines_isa_detach(struct gpib_board *board); - -enum ines_pci_vendor_ids { - PCI_VENDOR_ID_INES_QUICKLOGIC = 0x16da -}; - -enum ines_pci_device_ids { - PCI_DEVICE_ID_INES_GPIB_AMCC = 0x8507, - PCI_DEVICE_ID_INES_GPIB_QL5030 = 0x11, -}; - -enum ines_pci_subdevice_ids { - PCI_SUBDEVICE_ID_INES_GPIB = 0x1072 -}; - -static struct pci_device_id ines_pci_table[] = { - {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX, - PCI_SUBDEVICE_ID_INES_GPIB, 0, 0, 0}, - {PCI_VENDOR_ID_AMCC, PCI_DEVICE_ID_INES_GPIB_AMCC, PCI_VENDOR_ID_AMCC, - PCI_SUBDEVICE_ID_INES_GPIB, 0, 0, 0}, - {PCI_VENDOR_ID_INES_QUICKLOGIC, PCI_DEVICE_ID_INES_GPIB_QL5030, - PCI_VENDOR_ID_INES_QUICKLOGIC, PCI_DEVICE_ID_INES_GPIB_QL5030, 0, 0, 0}, - {PCI_DEVICE(PCI_VENDOR_ID_QUANCOM, PCI_DEVICE_ID_QUANCOM_GPIB)}, - {0} -}; -MODULE_DEVICE_TABLE(pci, ines_pci_table); - -struct ines_pci_id { - unsigned int vendor_id; - unsigned int device_id; - int subsystem_vendor_id; - int subsystem_device_id; - unsigned int gpib_region; - unsigned int io_offset; - enum ines_pci_chip pci_chip_type; -}; - -static struct ines_pci_id pci_ids[] = { - {.vendor_id = PCI_VENDOR_ID_PLX, - .device_id = PCI_DEVICE_ID_PLX_9050, - .subsystem_vendor_id = PCI_VENDOR_ID_PLX, - .subsystem_device_id = PCI_SUBDEVICE_ID_INES_GPIB, - .gpib_region = 2, - .io_offset = 1, - .pci_chip_type = PCI_CHIP_PLX9050, - }, - {.vendor_id = PCI_VENDOR_ID_AMCC, - .device_id = PCI_DEVICE_ID_INES_GPIB_AMCC, - .subsystem_vendor_id = PCI_VENDOR_ID_AMCC, - .subsystem_device_id = PCI_SUBDEVICE_ID_INES_GPIB, - .gpib_region = 1, - .io_offset = 1, - .pci_chip_type = PCI_CHIP_AMCC5920, - }, - {.vendor_id = PCI_VENDOR_ID_INES_QUICKLOGIC, - .device_id = PCI_DEVICE_ID_INES_GPIB_QL5030, - .subsystem_vendor_id = PCI_VENDOR_ID_INES_QUICKLOGIC, - .subsystem_device_id = PCI_DEVICE_ID_INES_GPIB_QL5030, - .gpib_region = 1, - .io_offset = 1, - .pci_chip_type = PCI_CHIP_QUICKLOGIC5030, - }, - {.vendor_id = PCI_VENDOR_ID_QUANCOM, - .device_id = PCI_DEVICE_ID_QUANCOM_GPIB, - .subsystem_vendor_id = -1, - .subsystem_device_id = -1, - .gpib_region = 0, - .io_offset = 4, - .pci_chip_type = PCI_CHIP_QUANCOM, - }, -}; - -static const int num_pci_chips = ARRAY_SIZE(pci_ids); - -// wrappers for interface functions -static int ines_read(struct gpib_board *board, u8 *buffer, size_t length, - int *end, size_t *bytes_read) -{ - struct ines_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - ssize_t retval; - int dummy; - - retval = nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); - if (retval < 0) { - write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR); - - set_bit(RFD_HOLDOFF_BN, &nec_priv->state); - - nec7210_read_data_in(board, nec_priv, &dummy); - } - return retval; -} - -static int ines_write(struct gpib_board *board, u8 *buffer, size_t length, int send_eoi, - size_t *bytes_written) -{ - struct ines_priv *priv = board->private_data; - - return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); -} - -static int ines_command(struct gpib_board *board, u8 *buffer, size_t length, size_t *bytes_written) -{ - struct ines_priv *priv = board->private_data; - - return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); -} - -static int ines_take_control(struct gpib_board *board, int synchronous) -{ - struct ines_priv *priv = board->private_data; - - return nec7210_take_control(board, &priv->nec7210_priv, synchronous); -} - -static int ines_go_to_standby(struct gpib_board *board) -{ - struct ines_priv *priv = board->private_data; - - return nec7210_go_to_standby(board, &priv->nec7210_priv); -} - -static int ines_request_system_control(struct gpib_board *board, int request_control) -{ - struct ines_priv *priv = board->private_data; - - return nec7210_request_system_control(board, &priv->nec7210_priv, request_control); -} - -static void ines_interface_clear(struct gpib_board *board, int assert) -{ - struct ines_priv *priv = board->private_data; - - nec7210_interface_clear(board, &priv->nec7210_priv, assert); -} - -static void ines_remote_enable(struct gpib_board *board, int enable) -{ - struct ines_priv *priv = board->private_data; - - nec7210_remote_enable(board, &priv->nec7210_priv, enable); -} - -static int ines_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits) -{ - struct ines_priv *priv = board->private_data; - - return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); -} - -static void ines_disable_eos(struct gpib_board *board) -{ - struct ines_priv *priv = board->private_data; - - nec7210_disable_eos(board, &priv->nec7210_priv); -} - -static unsigned int ines_update_status(struct gpib_board *board, unsigned int clear_mask) -{ - struct ines_priv *priv = board->private_data; - - return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); -} - -static int ines_primary_address(struct gpib_board *board, unsigned int address) -{ - struct ines_priv *priv = board->private_data; - - return nec7210_primary_address(board, &priv->nec7210_priv, address); -} - -static int ines_secondary_address(struct gpib_board *board, unsigned int address, int enable) -{ - struct ines_priv *priv = board->private_data; - - return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); -} - -static int ines_parallel_poll(struct gpib_board *board, u8 *result) -{ - struct ines_priv *priv = board->private_data; - - return nec7210_parallel_poll(board, &priv->nec7210_priv, result); -} - -static void ines_parallel_poll_configure(struct gpib_board *board, u8 config) -{ - struct ines_priv *priv = board->private_data; - - nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config); -} - -static void ines_parallel_poll_response(struct gpib_board *board, int ist) -{ - struct ines_priv *priv = board->private_data; - - nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); -} - -static void ines_serial_poll_response(struct gpib_board *board, u8 status) -{ - struct ines_priv *priv = board->private_data; - - nec7210_serial_poll_response(board, &priv->nec7210_priv, status); -} - -static u8 ines_serial_poll_status(struct gpib_board *board) -{ - struct ines_priv *priv = board->private_data; - - return nec7210_serial_poll_status(board, &priv->nec7210_priv); -} - -static void ines_return_to_local(struct gpib_board *board) -{ - struct ines_priv *priv = board->private_data; - - nec7210_return_to_local(board, &priv->nec7210_priv); -} - -static struct gpib_interface ines_pci_unaccel_interface = { - .name = "ines_pci_unaccel", - .attach = ines_pci_attach, - .detach = ines_pci_detach, - .read = ines_read, - .write = ines_write, - .command = ines_command, - .take_control = ines_take_control, - .go_to_standby = ines_go_to_standby, - .request_system_control = ines_request_system_control, - .interface_clear = ines_interface_clear, - .remote_enable = ines_remote_enable, - .enable_eos = ines_enable_eos, - .disable_eos = ines_disable_eos, - .parallel_poll = ines_parallel_poll, - .parallel_poll_configure = ines_parallel_poll_configure, - .parallel_poll_response = ines_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = ines_line_status, - .update_status = ines_update_status, - .primary_address = ines_primary_address, - .secondary_address = ines_secondary_address, - .serial_poll_response = ines_serial_poll_response, - .serial_poll_status = ines_serial_poll_status, - .t1_delay = ines_t1_delay, - .return_to_local = ines_return_to_local, -}; - -static struct gpib_interface ines_pci_interface = { - .name = "ines_pci", - .attach = ines_pci_accel_attach, - .detach = ines_pci_detach, - .read = ines_accel_read, - .write = ines_accel_write, - .command = ines_command, - .take_control = ines_take_control, - .go_to_standby = ines_go_to_standby, - .request_system_control = ines_request_system_control, - .interface_clear = ines_interface_clear, - .remote_enable = ines_remote_enable, - .enable_eos = ines_enable_eos, - .disable_eos = ines_disable_eos, - .parallel_poll = ines_parallel_poll, - .parallel_poll_configure = ines_parallel_poll_configure, - .parallel_poll_response = ines_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = ines_line_status, - .update_status = ines_update_status, - .primary_address = ines_primary_address, - .secondary_address = ines_secondary_address, - .serial_poll_response = ines_serial_poll_response, - .serial_poll_status = ines_serial_poll_status, - .t1_delay = ines_t1_delay, - .return_to_local = ines_return_to_local, -}; - -static struct gpib_interface ines_pci_accel_interface = { - .name = "ines_pci_accel", - .attach = ines_pci_accel_attach, - .detach = ines_pci_detach, - .read = ines_accel_read, - .write = ines_accel_write, - .command = ines_command, - .take_control = ines_take_control, - .go_to_standby = ines_go_to_standby, - .request_system_control = ines_request_system_control, - .interface_clear = ines_interface_clear, - .remote_enable = ines_remote_enable, - .enable_eos = ines_enable_eos, - .disable_eos = ines_disable_eos, - .parallel_poll = ines_parallel_poll, - .parallel_poll_configure = ines_parallel_poll_configure, - .parallel_poll_response = ines_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = ines_line_status, - .update_status = ines_update_status, - .primary_address = ines_primary_address, - .secondary_address = ines_secondary_address, - .serial_poll_response = ines_serial_poll_response, - .serial_poll_status = ines_serial_poll_status, - .t1_delay = ines_t1_delay, - .return_to_local = ines_return_to_local, -}; - -static struct gpib_interface ines_isa_interface = { - .name = "ines_isa", - .attach = ines_isa_attach, - .detach = ines_isa_detach, - .read = ines_accel_read, - .write = ines_accel_write, - .command = ines_command, - .take_control = ines_take_control, - .go_to_standby = ines_go_to_standby, - .request_system_control = ines_request_system_control, - .interface_clear = ines_interface_clear, - .remote_enable = ines_remote_enable, - .enable_eos = ines_enable_eos, - .disable_eos = ines_disable_eos, - .parallel_poll = ines_parallel_poll, - .parallel_poll_configure = ines_parallel_poll_configure, - .parallel_poll_response = ines_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = ines_line_status, - .update_status = ines_update_status, - .primary_address = ines_primary_address, - .secondary_address = ines_secondary_address, - .serial_poll_response = ines_serial_poll_response, - .serial_poll_status = ines_serial_poll_status, - .t1_delay = ines_t1_delay, - .return_to_local = ines_return_to_local, -}; - -static int ines_allocate_private(struct gpib_board *board) -{ - struct ines_priv *priv; - - board->private_data = kmalloc(sizeof(struct ines_priv), GFP_KERNEL); - if (!board->private_data) - return -1; - priv = board->private_data; - memset(priv, 0, sizeof(struct ines_priv)); - init_nec7210_private(&priv->nec7210_priv); - return 0; -} - -static void ines_free_private(struct gpib_board *board) -{ - kfree(board->private_data); - board->private_data = NULL; -} - -static int ines_generic_attach(struct gpib_board *board) -{ - struct ines_priv *ines_priv; - struct nec7210_priv *nec_priv; - - board->status = 0; - - if (ines_allocate_private(board)) - return -ENOMEM; - ines_priv = board->private_data; - nec_priv = &ines_priv->nec7210_priv; - nec_priv->read_byte = nec7210_ioport_read_byte; - nec_priv->write_byte = nec7210_ioport_write_byte; - nec_priv->offset = 1; - nec_priv->type = IGPIB7210; - ines_priv->pci_chip_type = PCI_CHIP_NONE; - - return 0; -} - -static void ines_online(struct ines_priv *ines_priv, const struct gpib_board *board, int use_accel) -{ - struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv; - - /* ines doesn't seem to use internal count register */ - write_byte(nec_priv, ICR | 0, AUXMR); - - write_byte(nec_priv, INES_AUX_XMODE, AUXMR); - write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR); - - set_bit(RFD_HOLDOFF_BN, &nec_priv->state); - - write_byte(nec_priv, INES_AUXD | 0, AUXMR); - ines_outb(ines_priv, 0, XDMA_CONTROL); - ines_priv->extend_mode_bits = 0; - ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE); - if (use_accel) { - ines_outb(ines_priv, 0x80, OUT_FIFO_WATERMARK); - ines_outb(ines_priv, 0x80, IN_FIFO_WATERMARK); - ines_outb(ines_priv, IFC_ACTIVE_BIT | ATN_ACTIVE_BIT | - FIFO_ERROR_BIT | XFER_COUNT_BIT, IMR3); - ines_outb(ines_priv, IN_FIFO_WATERMARK_BIT | IN_FIFO_FULL_BIT | - OUT_FIFO_WATERMARK_BIT | OUT_FIFO_EMPTY_BIT, IMR4); - } else { - nec7210_set_reg_bits(nec_priv, ADMR, IN_FIFO_ENABLE_BIT | OUT_FIFO_ENABLE_BIT, 0); - ines_outb(ines_priv, IFC_ACTIVE_BIT | FIFO_ERROR_BIT, IMR3); - ines_outb(ines_priv, 0, IMR4); - } - - nec7210_board_online(nec_priv, board); - if (use_accel) - nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, 0); -} - -static int ines_common_pci_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct ines_priv *ines_priv; - struct nec7210_priv *nec_priv; - int isr_flags = 0; - int retval; - struct ines_pci_id found_id; - unsigned int i; - struct pci_dev *pdev; - - memset(&found_id, 0, sizeof(found_id)); - - retval = ines_generic_attach(board); - if (retval) - return retval; - - ines_priv = board->private_data; - nec_priv = &ines_priv->nec7210_priv; - - // find board - ines_priv->pci_device = NULL; - for (i = 0; i < num_pci_chips && !ines_priv->pci_device; i++) { - pdev = NULL; - do { - if (pci_ids[i].subsystem_vendor_id >= 0 && - pci_ids[i].subsystem_device_id >= 0) - pdev = pci_get_subsys(pci_ids[i].vendor_id, pci_ids[i].device_id, - pci_ids[i].subsystem_vendor_id, - pci_ids[i].subsystem_device_id, pdev); - else - pdev = pci_get_device(pci_ids[i].vendor_id, pci_ids[i].device_id, - pdev); - if (!pdev) - break; - if (config->pci_bus >= 0 && config->pci_bus != pdev->bus->number) - continue; - if (config->pci_slot >= 0 && config->pci_slot != PCI_SLOT(pdev->devfn)) - continue; - found_id = pci_ids[i]; - ines_priv->pci_device = pdev; - break; - } while (1); - } - if (!ines_priv->pci_device) { - dev_err(board->gpib_dev, "could not find ines PCI board\n"); - return -1; - } - - if (pci_enable_device(ines_priv->pci_device)) { - dev_err(board->gpib_dev, "error enabling pci device\n"); - return -1; - } - - if (pci_request_regions(ines_priv->pci_device, DRV_NAME)) - return -1; - nec_priv->iobase = pci_resource_start(ines_priv->pci_device, - found_id.gpib_region); - - ines_priv->pci_chip_type = found_id.pci_chip_type; - nec_priv->offset = found_id.io_offset; - switch (ines_priv->pci_chip_type) { - case PCI_CHIP_PLX9050: - ines_priv->plx_iobase = pci_resource_start(ines_priv->pci_device, 1); - break; - case PCI_CHIP_AMCC5920: - ines_priv->amcc_iobase = pci_resource_start(ines_priv->pci_device, 0); - break; - case PCI_CHIP_QUANCOM: - break; - case PCI_CHIP_QUICKLOGIC5030: - break; - default: - dev_err(board->gpib_dev, "unspecified chip type? (bug)\n"); - nec_priv->iobase = 0; - pci_release_regions(ines_priv->pci_device); - return -1; - } - - nec7210_board_reset(nec_priv, board); -#ifdef QUANCOM_PCI - if (ines_priv->pci_chip_type == PCI_CHIP_QUANCOM) { - /* change interrupt polarity */ - nec_priv->auxb_bits |= HR_INV; - ines_outb(ines_priv, nec_priv->auxb_bits, AUXMR); - } -#endif - isr_flags |= IRQF_SHARED; - if (request_irq(ines_priv->pci_device->irq, ines_pci_interrupt, isr_flags, - DRV_NAME, board)) { - dev_err(board->gpib_dev, "can't request IRQ %d\n", ines_priv->pci_device->irq); - return -1; - } - ines_priv->irq = ines_priv->pci_device->irq; - - // enable interrupts on pci chip - switch (ines_priv->pci_chip_type) { - case PCI_CHIP_PLX9050: - outl(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR1_POLARITY_BIT | PLX9050_PCI_INTR_EN_BIT, - ines_priv->plx_iobase + PLX9050_INTCSR_REG); - break; - case PCI_CHIP_AMCC5920: - { - static const int region = 1; - static const int num_wait_states = 7; - u32 bits; - - bits = amcc_prefetch_bits(region, PREFETCH_DISABLED); - bits |= amcc_PTADR_mode_bit(region); - bits |= amcc_disable_write_fifo_bit(region); - bits |= amcc_wait_state_bits(region, num_wait_states); - outl(bits, ines_priv->amcc_iobase + AMCC_PASS_THRU_REG); - outl(AMCC_ADDON_INTR_ENABLE_BIT, ines_priv->amcc_iobase + AMCC_INTCS_REG); - } - break; - case PCI_CHIP_QUANCOM: - outb(QUANCOM_IRQ_ENABLE_BIT, nec_priv->iobase + - QUANCOM_IRQ_CONTROL_STATUS_REG); - break; - case PCI_CHIP_QUICKLOGIC5030: - break; - default: - dev_err(board->gpib_dev, "unspecified chip type? (bug)\n"); - return -1; - } - - return 0; -} - -static int ines_pci_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct ines_priv *ines_priv; - int retval; - - retval = ines_common_pci_attach(board, config); - if (retval < 0) - return retval; - - ines_priv = board->private_data; - ines_online(ines_priv, board, 0); - - return 0; -} - -static int ines_pci_accel_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct ines_priv *ines_priv; - int retval; - - retval = ines_common_pci_attach(board, config); - if (retval < 0) - return retval; - - ines_priv = board->private_data; - ines_online(ines_priv, board, 1); - - return 0; -} - -static const int ines_isa_iosize = 0x20; - -static int ines_isa_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct ines_priv *ines_priv; - struct nec7210_priv *nec_priv; - int isr_flags = 0; - int retval; - - retval = ines_generic_attach(board); - if (retval) - return retval; - - ines_priv = board->private_data; - nec_priv = &ines_priv->nec7210_priv; - - if (!request_region(config->ibbase, ines_isa_iosize, DRV_NAME)) { - dev_err(board->gpib_dev, "ioports at 0x%x already in use\n", - config->ibbase); - return -EBUSY; - } - nec_priv->iobase = config->ibbase; - nec_priv->offset = 1; - nec7210_board_reset(nec_priv, board); - if (request_irq(config->ibirq, ines_pci_interrupt, isr_flags, DRV_NAME, board)) { - dev_err(board->gpib_dev, "failed to allocate IRQ %d\n", config->ibirq); - return -1; - } - ines_priv->irq = config->ibirq; - ines_online(ines_priv, board, 1); - return 0; -} - -static void ines_pci_detach(struct gpib_board *board) -{ - struct ines_priv *ines_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (ines_priv) { - nec_priv = &ines_priv->nec7210_priv; - if (ines_priv->irq) { - // disable interrupts - switch (ines_priv->pci_chip_type) { - case PCI_CHIP_AMCC5920: - if (ines_priv->plx_iobase) - outl(0, ines_priv->plx_iobase + PLX9050_INTCSR_REG); - break; - case PCI_CHIP_QUANCOM: - if (nec_priv->iobase) - outb(0, nec_priv->iobase + - QUANCOM_IRQ_CONTROL_STATUS_REG); - break; - default: - break; - } - free_irq(ines_priv->irq, board); - } - if (nec_priv->iobase) { - nec7210_board_reset(nec_priv, board); - pci_release_regions(ines_priv->pci_device); - } - if (ines_priv->pci_device) - pci_dev_put(ines_priv->pci_device); - } - ines_free_private(board); -} - -static void ines_isa_detach(struct gpib_board *board) -{ - struct ines_priv *ines_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (ines_priv) { - nec_priv = &ines_priv->nec7210_priv; - if (ines_priv->irq) - free_irq(ines_priv->irq, board); - if (nec_priv->iobase) { - nec7210_board_reset(nec_priv, board); - release_region(nec_priv->iobase, ines_isa_iosize); - } - } - ines_free_private(board); -} - -static int ines_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - return 0; -} - -static struct pci_driver ines_pci_driver = { - .name = "ines_gpib", - .id_table = ines_pci_table, - .probe = &ines_pci_probe -}; - -#ifdef CONFIG_GPIB_PCMCIA - -#include <linux/kernel.h> -#include <linux/ptrace.h> -#include <linux/string.h> -#include <linux/timer.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/ds.h> -#include <pcmcia/cisreg.h> - -static const int ines_pcmcia_iosize = 0x20; - -/* - * The event() function is this driver's Card Services event handler. - * It will be called by Card Services when an appropriate card status - * event is received. The config() and release() entry points are - * used to configure or release a socket, in response to card insertion - * and ejection events. They are invoked from the gpib event - * handler. - */ - -static int ines_gpib_config(struct pcmcia_device *link); -static void ines_gpib_release(struct pcmcia_device *link); -static int ines_pcmcia_attach(struct gpib_board *board, const struct gpib_board_config *config); -static int ines_pcmcia_accel_attach(struct gpib_board *board, - const struct gpib_board_config *config); -static void ines_pcmcia_detach(struct gpib_board *board); -static int ines_common_pcmcia_attach(struct gpib_board *board); -/* - * A linked list of "instances" of the gpib device. Each actual - * PCMCIA card corresponds to one device instance, and is described - * by one dev_link_t structure (defined in ds.h). - * - * You may not want to use a linked list for this -- for example, the - * memory card driver uses an array of dev_link_t pointers, where minor - * device numbers are used to derive the corresponding array index. - */ - -static struct pcmcia_device *curr_dev; - -/* - * A dev_link_t structure has fields for most things that are needed - * to keep track of a socket, but there will usually be some device - * specific information that also needs to be kept track of. The - * 'priv' pointer in a dev_link_t structure can be used to point to - * a device-specific private data structure, like this. - * - * A driver needs to provide a dev_node_t structure for each device - * on a card. In some cases, there is only one device per card (for - * example, ethernet cards, modems). In other cases, there may be - * many actual or logical devices (SCSI adapters, memory cards with - * multiple partitions). The dev_node_t structures need to be kept - * in a linked list starting at the 'dev' field of a dev_link_t - * structure. We allocate them in the card's private data structure, - * because they generally can't be allocated dynamically. - */ - -struct local_info { - struct pcmcia_device *p_dev; - struct gpib_board *dev; - u_short manfid; - u_short cardid; -}; - -/* - * gpib_attach() creates an "instance" of the driver, allocating - * local data structures for one device. The device is registered - * with Card Services. - * - * The dev_link structure is initialized, but we don't actually - * configure the card at this point -- we wait until we receive a - * card insertion event. - */ -static int ines_gpib_probe(struct pcmcia_device *link) -{ - struct local_info *info; - -// int ret, i; - - /* Allocate space for private device-specific data */ - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - info->p_dev = link; - link->priv = info; - - /* The io structure describes IO port mapping */ - link->resource[0]->end = 32; - link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; - link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; - link->io_lines = 5; - - /* General socket configuration */ - link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - - /* Register with Card Services */ - curr_dev = link; - return ines_gpib_config(link); -} - -/* - * This deletes a driver "instance". The device is de-registered - * with Card Services. If it has been released, all local data - * structures are freed. Otherwise, the structures will be freed - * when the device is released. - */ -static void ines_gpib_remove(struct pcmcia_device *link) -{ - struct local_info *info = link->priv; - //struct struct gpib_board *dev = info->dev; - - if (info->dev) - ines_pcmcia_detach(info->dev); - ines_gpib_release(link); - - //free_netdev(dev); - kfree(info); -} - -static int ines_gpib_config_iteration(struct pcmcia_device *link, void *priv_data) -{ - return pcmcia_request_io(link); -} - -/* - * gpib_config() is scheduled to run after a CARD_INSERTION event - * is received, to configure the PCMCIA socket, and to make the - * device available to the system. - */ -static int ines_gpib_config(struct pcmcia_device *link) -{ - int retval; - void __iomem *virt; - - retval = pcmcia_loop_config(link, &ines_gpib_config_iteration, NULL); - if (retval) { - dev_warn(&link->dev, "no configuration found\n"); - ines_gpib_release(link); - return -ENODEV; - } - - dev_dbg(&link->dev, "ines_cs: manufacturer: 0x%x card: 0x%x\n", - link->manf_id, link->card_id); - - /* - * for the ines card we have to setup the configuration registers in - * attribute memory here - */ - link->resource[2]->flags |= WIN_MEMORY_TYPE_AM | WIN_DATA_WIDTH_8 | WIN_ENABLE; - link->resource[2]->end = 0x1000; - retval = pcmcia_request_window(link, link->resource[2], 250); - if (retval) { - dev_warn(&link->dev, "pcmcia_request_window failed\n"); - ines_gpib_release(link); - return -ENODEV; - } - retval = pcmcia_map_mem_page(link, link->resource[2], 0); - if (retval) { - dev_warn(&link->dev, "pcmcia_map_mem_page failed\n"); - ines_gpib_release(link); - return -ENODEV; - } - virt = ioremap(link->resource[2]->start, resource_size(link->resource[2])); - writeb((link->resource[2]->start >> 2) & 0xff, virt + 0xf0); // IOWindow base - iounmap(virt); - - /* - * This actually configures the PCMCIA socket -- setting up - * the I/O windows and the interrupt mapping. - */ - retval = pcmcia_enable_device(link); - if (retval) { - ines_gpib_release(link); - return -ENODEV; - } - return 0; -} /* gpib_config */ - -/* - * After a card is removed, gpib_release() will unregister the net - * device, and release the PCMCIA configuration. If the device is - * still open, this will be postponed until it is closed. - */ - -static void ines_gpib_release(struct pcmcia_device *link) -{ - pcmcia_disable_device(link); -} /* gpib_release */ - -static int ines_gpib_suspend(struct pcmcia_device *link) -{ - //struct local_info *info = link->priv; - //struct struct gpib_board *dev = info->dev; - - if (link->open) - dev_err(&link->dev, "Device still open\n"); - //netif_device_detach(dev); - - return 0; -} - -static int ines_gpib_resume(struct pcmcia_device *link) -{ - //struct local_info_t *info = link->priv; - //struct struct gpib_board *dev = info->dev; - - /*if (link->open) { - * ni_gpib_probe(dev); / really? - * //netif_device_attach(dev); - *} - */ - return ines_gpib_config(link); -} - -static struct pcmcia_device_id ines_pcmcia_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x01b4, 0x4730), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, ines_pcmcia_ids); - -static struct pcmcia_driver ines_gpib_cs_driver = { - .owner = THIS_MODULE, - .name = "ines_gpib_cs", - .id_table = ines_pcmcia_ids, - .probe = ines_gpib_probe, - .remove = ines_gpib_remove, - .suspend = ines_gpib_suspend, - .resume = ines_gpib_resume, -}; - -static void ines_pcmcia_cleanup_module(void) -{ - pcmcia_unregister_driver(&ines_gpib_cs_driver); -} - -static struct gpib_interface ines_pcmcia_unaccel_interface = { - .name = "ines_pcmcia_unaccel", - .attach = ines_pcmcia_attach, - .detach = ines_pcmcia_detach, - .read = ines_read, - .write = ines_write, - .command = ines_command, - .take_control = ines_take_control, - .go_to_standby = ines_go_to_standby, - .request_system_control = ines_request_system_control, - .interface_clear = ines_interface_clear, - .remote_enable = ines_remote_enable, - .enable_eos = ines_enable_eos, - .disable_eos = ines_disable_eos, - .parallel_poll = ines_parallel_poll, - .parallel_poll_configure = ines_parallel_poll_configure, - .parallel_poll_response = ines_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = ines_line_status, - .update_status = ines_update_status, - .primary_address = ines_primary_address, - .secondary_address = ines_secondary_address, - .serial_poll_response = ines_serial_poll_response, - .serial_poll_status = ines_serial_poll_status, - .t1_delay = ines_t1_delay, - .return_to_local = ines_return_to_local, -}; - -static struct gpib_interface ines_pcmcia_accel_interface = { - .name = "ines_pcmcia_accel", - .attach = ines_pcmcia_accel_attach, - .detach = ines_pcmcia_detach, - .read = ines_accel_read, - .write = ines_accel_write, - .command = ines_command, - .take_control = ines_take_control, - .go_to_standby = ines_go_to_standby, - .request_system_control = ines_request_system_control, - .interface_clear = ines_interface_clear, - .remote_enable = ines_remote_enable, - .enable_eos = ines_enable_eos, - .disable_eos = ines_disable_eos, - .parallel_poll = ines_parallel_poll, - .parallel_poll_configure = ines_parallel_poll_configure, - .parallel_poll_response = ines_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = ines_line_status, - .update_status = ines_update_status, - .primary_address = ines_primary_address, - .secondary_address = ines_secondary_address, - .serial_poll_response = ines_serial_poll_response, - .serial_poll_status = ines_serial_poll_status, - .t1_delay = ines_t1_delay, - .return_to_local = ines_return_to_local, -}; - -static struct gpib_interface ines_pcmcia_interface = { - .name = "ines_pcmcia", - .attach = ines_pcmcia_accel_attach, - .detach = ines_pcmcia_detach, - .read = ines_accel_read, - .write = ines_accel_write, - .command = ines_command, - .take_control = ines_take_control, - .go_to_standby = ines_go_to_standby, - .request_system_control = ines_request_system_control, - .interface_clear = ines_interface_clear, - .remote_enable = ines_remote_enable, - .enable_eos = ines_enable_eos, - .disable_eos = ines_disable_eos, - .parallel_poll = ines_parallel_poll, - .parallel_poll_configure = ines_parallel_poll_configure, - .parallel_poll_response = ines_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = ines_line_status, - .update_status = ines_update_status, - .primary_address = ines_primary_address, - .secondary_address = ines_secondary_address, - .serial_poll_response = ines_serial_poll_response, - .serial_poll_status = ines_serial_poll_status, - .t1_delay = ines_t1_delay, - .return_to_local = ines_return_to_local, -}; - -static irqreturn_t ines_pcmcia_interrupt(int irq, void *arg) -{ - struct gpib_board *board = arg; - - return ines_interrupt(board); -} - -static int ines_common_pcmcia_attach(struct gpib_board *board) -{ - struct ines_priv *ines_priv; - struct nec7210_priv *nec_priv; - int retval; - - if (!curr_dev) { - dev_err(board->gpib_dev, "no ines pcmcia cards found\n"); - return -1; - } - - retval = ines_generic_attach(board); - if (retval) - return retval; - - ines_priv = board->private_data; - nec_priv = &ines_priv->nec7210_priv; - - if (!request_region(curr_dev->resource[0]->start, - resource_size(curr_dev->resource[0]), DRV_NAME)) { - dev_err(board->gpib_dev, "ioports at 0x%lx already in use\n", - (unsigned long)(curr_dev->resource[0]->start)); - return -1; - } - - nec_priv->iobase = curr_dev->resource[0]->start; - - nec7210_board_reset(nec_priv, board); - - if (request_irq(curr_dev->irq, ines_pcmcia_interrupt, IRQF_SHARED, - "pcmcia-gpib", board)) { - dev_err(board->gpib_dev, "can't request IRQ %d\n", curr_dev->irq); - return -1; - } - ines_priv->irq = curr_dev->irq; - - return 0; -} - -static int ines_pcmcia_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct ines_priv *ines_priv; - int retval; - - retval = ines_common_pcmcia_attach(board); - if (retval < 0) - return retval; - - ines_priv = board->private_data; - ines_online(ines_priv, board, 0); - - return 0; -} - -static int ines_pcmcia_accel_attach(struct gpib_board *board, - const struct gpib_board_config *config) -{ - struct ines_priv *ines_priv; - int retval; - - retval = ines_common_pcmcia_attach(board); - if (retval < 0) - return retval; - - ines_priv = board->private_data; - ines_online(ines_priv, board, 1); - - return 0; -} - -static void ines_pcmcia_detach(struct gpib_board *board) -{ - struct ines_priv *ines_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (ines_priv) { - nec_priv = &ines_priv->nec7210_priv; - if (ines_priv->irq) - free_irq(ines_priv->irq, board); - if (nec_priv->iobase) { - nec7210_board_reset(nec_priv, board); - release_region(nec_priv->iobase, ines_pcmcia_iosize); - } - } - ines_free_private(board); -} - -#endif /* CONFIG_GPIB_PCMCIA */ - -static int __init ines_init_module(void) -{ - int ret; - - ret = pci_register_driver(&ines_pci_driver); - if (ret) { - pr_err("pci_register_driver failed: error = %d\n", ret); - return ret; - } - - ret = gpib_register_driver(&ines_pci_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pci; - } - - ret = gpib_register_driver(&ines_pci_unaccel_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pci_unaccel; - } - - ret = gpib_register_driver(&ines_pci_accel_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pci_accel; - } - - ret = gpib_register_driver(&ines_isa_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_isa; - } - -#ifdef CONFIG_GPIB_PCMCIA - ret = gpib_register_driver(&ines_pcmcia_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pcmcia; - } - - ret = gpib_register_driver(&ines_pcmcia_unaccel_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pcmcia_unaccel; - } - - ret = gpib_register_driver(&ines_pcmcia_accel_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pcmcia_accel; - } - - ret = pcmcia_register_driver(&ines_gpib_cs_driver); - if (ret) { - pr_err("pcmcia_register_driver failed: error = %d\n", ret); - goto err_pcmcia_driver; - } -#endif - - return 0; - -#ifdef CONFIG_GPIB_PCMCIA -err_pcmcia_driver: - gpib_unregister_driver(&ines_pcmcia_accel_interface); -err_pcmcia_accel: - gpib_unregister_driver(&ines_pcmcia_unaccel_interface); -err_pcmcia_unaccel: - gpib_unregister_driver(&ines_pcmcia_interface); -err_pcmcia: -#endif - gpib_unregister_driver(&ines_isa_interface); -err_isa: - gpib_unregister_driver(&ines_pci_accel_interface); -err_pci_accel: - gpib_unregister_driver(&ines_pci_unaccel_interface); -err_pci_unaccel: - gpib_unregister_driver(&ines_pci_interface); -err_pci: - pci_unregister_driver(&ines_pci_driver); - - return ret; -} - -static void __exit ines_exit_module(void) -{ - gpib_unregister_driver(&ines_pci_interface); - gpib_unregister_driver(&ines_pci_unaccel_interface); - gpib_unregister_driver(&ines_pci_accel_interface); - gpib_unregister_driver(&ines_isa_interface); -#ifdef CONFIG_GPIB_PCMCIA - gpib_unregister_driver(&ines_pcmcia_interface); - gpib_unregister_driver(&ines_pcmcia_unaccel_interface); - gpib_unregister_driver(&ines_pcmcia_accel_interface); - ines_pcmcia_cleanup_module(); -#endif - - pci_unregister_driver(&ines_pci_driver); -} - -module_init(ines_init_module); -module_exit(ines_exit_module); diff --git a/drivers/staging/gpib/lpvo_usb_gpib/Makefile b/drivers/staging/gpib/lpvo_usb_gpib/Makefile deleted file mode 100644 index 360553488e6d..000000000000 --- a/drivers/staging/gpib/lpvo_usb_gpib/Makefile +++ /dev/null @@ -1,3 +0,0 @@ - -obj-$(CONFIG_GPIB_LPVO) += lpvo_usb_gpib.o - diff --git a/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c b/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c deleted file mode 100644 index dd68c4843490..000000000000 --- a/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c +++ /dev/null @@ -1,2025 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * This code has been developed at the Department of Physics (University * - * of Florence, Italy) to support in linux-gpib the open usb-gpib adapter * - * implemented at the University of Ljubljana (lpvo.fe.uni-lj.si/gpib) * - * * - * copyright : (C) 2011 Marcello Carla' * - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define NAME KBUILD_MODNAME - -/* base module includes */ - -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/tty.h> -#include <linux/types.h> -#include <linux/slab.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <linux/spinlock.h> -#include <linux/file.h> -#include <linux/timer.h> -#include <linux/delay.h> -#include <linux/sched/signal.h> -#include <linux/usb.h> - -#include "gpibP.h" - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB driver for LPVO usb devices"); - -/* - * Table of devices that work with this driver. - * - * Currently, only one device is known to be used in the - * lpvo_usb_gpib adapter (FTDI 0403:6001). - * If your adapter uses a different chip, insert a line - * in the following table with proper <Vendor-id>, <Product-id>. - * - * To have your chip automatically handled by the driver, - * update files "/usr/local/etc/modprobe.d/lpvo_usb_gpib.conf" - * and /usr/local/etc/udev/rules.d/99-lpvo_usb_gpib.rules. - * - */ - -static const struct usb_device_id skel_table[] = { - { USB_DEVICE(0x0403, 0x6001) }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, skel_table); - -/* - * *** Diagnostics and Debug *** - * To enable the diagnostic and debug messages either compile with DEBUG set - * or control via the dynamic debug mechanisms. - * The module parameter "debug" controls the sending of debug messages to - * syslog. By default it is set to 0 - * debug = 0: only attach/detach messages are sent - * 1: every action is logged - * 2: extended logging; each single exchanged byte is documented - * (about twice the log volume of [1]) - * To switch debug level: - * At module loading: modprobe lpvo_usb_gpib debug={0,1,2} - * On the fly: echo {0,1,2} > /sys/modules/lpvo_usb_gpib/parameters/debug - */ - -static int debug; -module_param(debug, int, 0644); - -#define DIA_LOG(level, format, ...) \ - do { if (debug >= (level)) \ - dev_dbg(board->gpib_dev, format, ## __VA_ARGS__); } \ - while (0) - -#define WQT wait_queue_entry_t -#define WQH head -#define WQE entry - -/* standard and extended command sets of the usb-gpib adapter */ - -#define USB_GPIB_ON "\nIB\n" -#define USB_GPIB_OFF "\nIBO\n" -#define USB_GPIB_IBm0 "\nIBm0\n" /* do not assert REN with IFC */ -#define USB_GPIB_IBm1 "\nIBm1\n" /* assert REN with IFC */ -#define USB_GPIB_IBCL "\nIBZ\n" -#define USB_GPIB_STATUS "\nIBS\n" -#define USB_GPIB_READ "\nIB?\n" -#define USB_GPIB_READ_1 "\nIBB\n" -#define USB_GPIB_EOI "\nIBe0\n" -#define USB_GPIB_FTMO "\nIBf0\n" /* disable first byte timeout */ -#define USB_GPIB_TTMOZ "\nIBt0\n" /* disable byte timeout */ - -/* incomplete commands */ - -#define USB_GPIB_BTMO "\nIBt" /* set byte timeout */ -#define USB_GPIB_TTMO "\nIBT" /* set total timeout */ - -#define USB_GPIB_DEBUG_ON "\nIBDE\xAA\n" -#define USB_GPIB_SET_LISTEN "\nIBDT0\n" -#define USB_GPIB_SET_TALK "\nIBDT1\n" -#define USB_GPIB_SET_LINES "\nIBDC.\n" -#define USB_GPIB_SET_DATA "\nIBDM.\n" -#define USB_GPIB_READ_LINES "\nIBD?C\n" -#define USB_GPIB_READ_DATA "\nIBD?M\n" -#define USB_GPIB_READ_BUS "\nIBD??\n" - -/* command sequences */ - -#define USB_GPIB_UNTALK "\nIBC_\n" -#define USB_GPIB_UNLISTEN "\nIBC?\n" - -/* special characters used by the adapter */ - -#define DLE ('\020') -#define STX ('\02') -#define ETX ('\03') -#define ACK ('\06') -#define NODATA ('\03') -#define NODAV ('\011') - -#define IB_BUS_REN 0x01 -#define IB_BUS_IFC 0x02 -#define IB_BUS_NDAC 0x04 -#define IB_BUS_NRFD 0x08 -#define IB_BUS_DAV 0x10 -#define IB_BUS_EOI 0x20 -#define IB_BUS_ATN 0x40 -#define IB_BUS_SRQ 0x80 - -#define INBUF_SIZE 128 - -struct char_buf { /* used by one_char() routine */ - char *inbuf; - int last; - int nchar; -}; - -struct usb_gpib_priv { /* private data to the device */ - u8 eos; /* eos character */ - short eos_flags; /* eos mode */ - int timeout; /* current value for timeout */ - void *dev; /* the usb device private data structure */ -}; - -#define GPIB_DEV (((struct usb_gpib_priv *)board->private_data)->dev) - -static void show_status(struct gpib_board *board) -{ - DIA_LOG(2, "# - buffer_length %d\n", board->buffer_length); - DIA_LOG(2, "# - status %lx\n", board->status); - DIA_LOG(2, "# - use_count %d\n", board->use_count); - DIA_LOG(2, "# - pad %x\n", board->pad); - DIA_LOG(2, "# - sad %x\n", board->sad); - DIA_LOG(2, "# - timeout %d\n", board->usec_timeout); - DIA_LOG(2, "# - ppc %d\n", board->parallel_poll_configuration); - DIA_LOG(2, "# - t1delay %d\n", board->t1_nano_sec); - DIA_LOG(2, "# - online %d\n", board->online); - DIA_LOG(2, "# - autopoll %d\n", board->autospollers); - DIA_LOG(2, "# - autopoll task %p\n", board->autospoll_task); - DIA_LOG(2, "# - minor %d\n", board->minor); - DIA_LOG(2, "# - master %d\n", board->master); - DIA_LOG(2, "# - list %d\n", board->ist); -} - -/* - * GLOBAL VARIABLES: required for - * pairing among gpib minor and usb minor. - * MAX_DEV is the max number of usb-gpib adapters; free - * to change as you like, but no more than 32 - */ - -#define MAX_DEV 8 -static struct usb_interface *lpvo_usb_interfaces[MAX_DEV]; /* registered interfaces */ -static int usb_minors[MAX_DEV]; /* usb minors */ -static int assigned_usb_minors; /* mask of filled slots */ -static struct mutex minors_lock; /* operations on usb_minors are to be protected */ - -/* - * usb-skeleton prototypes - */ - -struct usb_skel; -static ssize_t skel_do_write(struct usb_skel *, const char *, size_t); -static ssize_t skel_do_read(struct usb_skel *, char *, size_t); -static int skel_do_open(struct gpib_board *, int); -static int skel_do_release(struct gpib_board *); - -/* - * usec_diff : take difference in MICROsec between two 'timespec' - * (unix time in sec and NANOsec) - */ - -static inline int usec_diff(struct timespec64 *a, struct timespec64 *b) -{ - return ((a->tv_sec - b->tv_sec) * 1000000 + - (a->tv_nsec - b->tv_nsec) / 1000); -} - -/* - * *** these routines are specific to the usb-gpib adapter *** - */ - -/** - * write_loop() - Send a byte sequence to the adapter - * - * @dev: the private device structure - * @msg: the byte sequence. - * @leng: the byte sequence length. - * - */ - -static int write_loop(void *dev, char *msg, int leng) -{ - return skel_do_write(dev, msg, leng); -} - -/** - * send_command() - Send a byte sequence and return a single byte reply. - * - * @board: the gpib_board_struct data area for this gpib interface - * @msg: the byte sequence. - * @leng: the byte sequence length; can be given as zero and is - * computed automatically, but if 'msg' contains a zero byte, - * it has to be given explicitly. - */ - -static int send_command(struct gpib_board *board, char *msg, int leng) -{ - char buffer[64]; - int nchar; - int retval; - struct timespec64 before, after; - - ktime_get_real_ts64 (&before); - - if (!leng) - leng = strlen(msg); - retval = write_loop(GPIB_DEV, msg, leng); - if (retval < 0) - return retval; - - nchar = skel_do_read(GPIB_DEV, buffer, 64); - - if (nchar < 0) { - dev_err(board->gpib_dev, " return from read: %d\n", nchar); - return nchar; - } else if (nchar != 1) { - dev_err(board->gpib_dev, " Irregular reply to command: %s\n", msg); - return -EIO; - } - ktime_get_real_ts64 (&after); - - DIA_LOG(1, "Sent %d - done %d us.\n", leng, usec_diff(&after, &before)); - - return buffer[0] & 0xff; -} - -/* - * set_control_line() - Set the value of a single gpib control line - * - * @board: the gpib_board_struct data area for this gpib interface - * @line: line mask - * @value: line new value (0/1) - */ - -static int set_control_line(struct gpib_board *board, int line, int value) -{ - char msg[] = USB_GPIB_SET_LINES; - int retval; - int leng = strlen(msg); - - DIA_LOG(1, "setting line %x to %x\n", line, value); - - retval = send_command(board, USB_GPIB_READ_LINES, 0); - - DIA_LOG(1, "old line values: %x\n", retval); - - if (retval == -EIO) - return retval; - - msg[leng - 2] = value ? (retval & ~line) : retval | line; - - retval = send_command(board, msg, 0); - - DIA_LOG(1, "operation result: %x\n", retval); - - return retval; -} - -/* - * one_char() - read one single byte from input buffer - * - * @board: the gpib_board_struct data area for this gpib interface - * @char_buf: the routine private data structure - */ - -static int one_char(struct gpib_board *board, struct char_buf *b) -{ - struct timespec64 before, after; - - if (b->nchar) { - DIA_LOG(2, "-> %x\n", b->inbuf[b->last - b->nchar]); - return b->inbuf[b->last - b->nchar--]; - } - ktime_get_real_ts64 (&before); - b->nchar = skel_do_read(GPIB_DEV, b->inbuf, INBUF_SIZE); - b->last = b->nchar; - ktime_get_real_ts64 (&after); - - DIA_LOG(2, "read %d bytes in %d usec\n", - b->nchar, usec_diff(&after, &before)); - - if (b->nchar > 0) { - DIA_LOG(2, "--> %x\n", b->inbuf[b->last - b->nchar]); - return b->inbuf[b->last - b->nchar--]; - } - return -EIO; -} - -/** - * set_timeout() - set single byte / total timeouts on the adapter - * - * @board: the gpib_board_struct data area for this gpib interface - * - * For sake of speed, the operation is performed only if it - * modifies the current (saved) value. Minimum allowed timeout - * is 30 ms (T30ms -> 8); timeout disable (TNONE -> 0) currently - * not supported. - */ - -static void set_timeout(struct gpib_board *board) -{ - int n, val; - char command[sizeof(USB_GPIB_TTMO) + 6]; - struct usb_gpib_priv *data = board->private_data; - - if (data->timeout == board->usec_timeout) - return; - - n = (board->usec_timeout + 32767) / 32768; - if (n < 2) - n = 2; - - DIA_LOG(1, "Set timeout to %d us -> %d\n", board->usec_timeout, n); - - sprintf(command, "%s%d\n", USB_GPIB_BTMO, n > 255 ? 255 : n); - val = send_command(board, command, 0); - - if (val == ACK) { - if (n > 65535) - n = 65535; - sprintf(command, "%s%d\n", USB_GPIB_TTMO, n); - val = send_command(board, command, 0); - } - - if (val != ACK) - dev_err(board->gpib_dev, "error in timeout set: <%s>\n", command); - else - data->timeout = board->usec_timeout; -} - -/* - * now the standard interface functions - attach and detach - */ - -/** - * usb_gpib_attach() - activate the usb-gpib converter board - * - * @board: the gpib_board_struct data area for this gpib interface - * @config: firmware data, if any (from gpib_config -I <file>) - * - * The channel name is ttyUSBn, with n=0 by default. Other values for n - * passed with gpib_config -b <n>. - * - * In this routine I trust that when an error code is returned - * detach() will be called. Always. - */ - -static int usb_gpib_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - int retval, j; - u32 base = config->ibbase; - char *device_path; - int match; - struct usb_device *udev; - - DIA_LOG(0, "Board %p -t %s -m %d -a %p -u %d -l %d -b %d\n", - board, board->interface->name, board->minor, config->device_path, - config->pci_bus, config->pci_slot, base); - - board->private_data = NULL; /* to be sure - we can detach before setting */ - - /* identify device to be attached */ - - mutex_lock(&minors_lock); - - if (config->device_path) { - /* if config->device_path given, try that first */ - for (j = 0 ; j < MAX_DEV ; j++) { - if ((assigned_usb_minors & 1 << j) == 0) - continue; - udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j])); - device_path = kobject_get_path(&udev->dev.kobj, GFP_KERNEL); - match = gpib_match_device_path(&lpvo_usb_interfaces[j]->dev, - config->device_path); - DIA_LOG(1, "dev. %d: minor %d path: %s --> %d\n", j, - lpvo_usb_interfaces[j]->minor, device_path, match); - kfree(device_path); - if (match) - break; - } - } else if (config->pci_bus != -1 && config->pci_slot != -1) { - /* second: look for bus and slot */ - for (j = 0 ; j < MAX_DEV ; j++) { - if ((assigned_usb_minors & 1 << j) == 0) - continue; - udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j])); - DIA_LOG(1, "dev. %d: bus %d -> %d dev: %d -> %d\n", j, - udev->bus->busnum, config->pci_bus, udev->devnum, config->pci_slot); - if (config->pci_bus == udev->bus->busnum && - config->pci_slot == udev->devnum) - break; - } - } else { /* last chance: usb_minor, given as ibbase */ - for (j = 0 ; j < MAX_DEV ; j++) { - if (usb_minors[j] == base && assigned_usb_minors & 1 << j) - break; - } - } - mutex_unlock(&minors_lock); - - if (j == MAX_DEV) { - dev_err(board->gpib_dev, "Requested device is not registered.\n"); - return -EIO; - } - - board->private_data = kzalloc(sizeof(struct usb_gpib_priv), GFP_KERNEL); - if (!board->private_data) - return -ENOMEM; - - retval = skel_do_open(board, usb_minors[j]); - - DIA_LOG(1, "Skel open: %d\n", retval); - - if (retval) { - dev_err(board->gpib_dev, "skel open failed.\n"); - kfree(board->private_data); - board->private_data = NULL; - return -ENODEV; - } - - show_status(board); - - retval = send_command(board, USB_GPIB_ON, 0); - DIA_LOG(1, "USB_GPIB_ON returns %x\n", retval); - if (retval != ACK) - return -EIO; - - /* - * We must setup debug mode because we need the extended instruction - * set to cope with the Core (gpib_common) point of view - */ - - retval = send_command(board, USB_GPIB_DEBUG_ON, 0); - DIA_LOG(1, "USB_GPIB_DEBUG_ON returns %x\n", retval); - if (retval != ACK) - return -EIO; - - /* - * We must keep REN off after an IFC because so it is - * assumed by the Core - */ - - retval = send_command(board, USB_GPIB_IBm0, 0); - DIA_LOG(1, "USB_GPIB_IBm0 returns %x\n", retval); - if (retval != ACK) - return -EIO; - - retval = set_control_line(board, IB_BUS_REN, 0); - if (retval != ACK) - return -EIO; - - retval = send_command(board, USB_GPIB_FTMO, 0); - DIA_LOG(1, "USB_GPIB_FTMO returns %x\n", retval); - if (retval != ACK) - return -EIO; - - show_status(board); - DIA_LOG(0, "attached\n"); - return 0; -} - -/** - * usb_gpib_detach() - deactivate the usb-gpib converter board - * - * @board: the gpib_board data area for this gpib interface - * - */ - -static void usb_gpib_detach(struct gpib_board *board) -{ - int retval; - - show_status(board); - - DIA_LOG(0, "detaching\n"); - - if (board->private_data) { - if (GPIB_DEV) { - write_loop(GPIB_DEV, USB_GPIB_OFF, strlen(USB_GPIB_OFF)); - msleep(100); - DIA_LOG(1, "%s", "GPIB off\n"); - retval = skel_do_release(board); - DIA_LOG(1, "skel release -> %d\n", retval); - } - kfree(board->private_data); - board->private_data = NULL; - } - - DIA_LOG(0, "detached\n"); -} - -/* - * Other functions follow in alphabetical order - */ -/* command */ -static int usb_gpib_command(struct gpib_board *board, - u8 *buffer, - size_t length, - size_t *bytes_written) -{ - int i, retval; - char command[6] = "IBc.\n"; - - DIA_LOG(1, "enter %p\n", board); - - set_timeout(board); - - *bytes_written = 0; - for (i = 0 ; i < length ; i++) { - command[3] = buffer[i]; - retval = send_command(board, command, 5); - DIA_LOG(2, "%d ==> %x %x\n", i, buffer[i], retval); - if (retval != 0x06) - return retval; - ++(*bytes_written); - } - return 0; -} - -/** - * usb_gpib_disable_eos() - Disable END on eos byte (END on EOI only) - * - * @board: the gpib_board data area for this gpib interface - * - * With the lpvo adapter eos can only be handled via software. - * Cannot do nothing here, but remember for future use. - */ - -static void usb_gpib_disable_eos(struct gpib_board *board) -{ - ((struct usb_gpib_priv *)board->private_data)->eos_flags &= ~REOS; - DIA_LOG(1, "done: %x\n", - ((struct usb_gpib_priv *)board->private_data)->eos_flags); -} - -/** - * usb_gpib_enable_eos() - Enable END for reads when eos byte is received. - * - * @board: the gpib_board data area for this gpib interface - * @eos_byte: the 'eos' byte - * @compare_8_bits: if zero ignore eigthth bit when comparing - * - */ - -static int usb_gpib_enable_eos(struct gpib_board *board, - u8 eos_byte, - int compare_8_bits) -{ - struct usb_gpib_priv *pd = (struct usb_gpib_priv *)board->private_data; - - DIA_LOG(1, "enter with %x\n", eos_byte); - pd->eos = eos_byte; - pd->eos_flags = REOS; - if (compare_8_bits) - pd->eos_flags |= BIN; - return 0; -} - -/** - * usb_gpib_go_to_standby() - De-assert ATN - * - * @board: the gpib_board data area for this gpib interface - */ - -static int usb_gpib_go_to_standby(struct gpib_board *board) -{ - int retval = set_control_line(board, IB_BUS_ATN, 0); - - DIA_LOG(1, "done with %x\n", retval); - - if (retval == ACK) - return 0; - return -EIO; -} - -/** - * usb_gpib_interface_clear() - Assert or de-assert IFC - * - * @board: the gpib_board data area for this gpib interface - * @assert: 1: assert IFC; 0: de-assert IFC - * - * Currently on the assert request we issue the lpvo IBZ - * command that cycles IFC low for 100 usec, then we ignore - * the de-assert request. - */ - -static void usb_gpib_interface_clear(struct gpib_board *board, int assert) -{ - int retval = 0; - - DIA_LOG(1, "enter with %d\n", assert); - - if (assert) { - retval = send_command(board, USB_GPIB_IBCL, 0); - - set_bit(CIC_NUM, &board->status); - } - - DIA_LOG(1, "done with %d %d\n", assert, retval); -} - -/** - * usb_gpib_line_status() - Read the status of the bus lines. - * - * @board: the gpib_board data area for this gpib interface - * - * We can read all lines. - */ -static int usb_gpib_line_status(const struct gpib_board *board) -{ - int buffer; - int line_status = VALID_ALL; /* all lines will be read */ - struct list_head *p, *q; - WQT *item; - unsigned long flags; - int sleep = 0; - - DIA_LOG(1, "%s\n", "request"); - - /* - * if we are on the wait queue (board->wait), do not hurry - * reading status line; instead, pause a little - */ - - spin_lock_irqsave((spinlock_t *)&board->wait.lock, flags); - q = (struct list_head *)&board->wait.WQH; - list_for_each(p, q) { - item = container_of(p, WQT, WQE); - if (item->private == current) { - sleep = 20; - break; - } - /* pid is: ((struct task_struct *) item->private)->pid); */ - } - spin_unlock_irqrestore((spinlock_t *)&board->wait.lock, flags); - if (sleep) { - DIA_LOG(1, "we are on the wait queue - sleep %d ms\n", sleep); - msleep(sleep); - } - - buffer = send_command((struct gpib_board *)board, USB_GPIB_STATUS, 0); - - if (buffer < 0) { - dev_err(board->gpib_dev, "line status read failed with %d\n", buffer); - return -1; - } - - if ((buffer & 0x01) == 0) - line_status |= BUS_REN; - if ((buffer & 0x02) == 0) - line_status |= BUS_IFC; - if ((buffer & 0x04) == 0) - line_status |= BUS_NDAC; - if ((buffer & 0x08) == 0) - line_status |= BUS_NRFD; - if ((buffer & 0x10) == 0) - line_status |= BUS_DAV; - if ((buffer & 0x20) == 0) - line_status |= BUS_EOI; - if ((buffer & 0x40) == 0) - line_status |= BUS_ATN; - if ((buffer & 0x80) == 0) - line_status |= BUS_SRQ; - - DIA_LOG(1, "done with %x %x\n", buffer, line_status); - - return line_status; -} - -/* parallel_poll */ - -static int usb_gpib_parallel_poll(struct gpib_board *board, u8 *result) -{ - /* - * request parallel poll asserting ATN | EOI; - * we suppose ATN already asserted - */ - - int retval; - - DIA_LOG(1, "enter %p\n", board); - - retval = set_control_line(board, IB_BUS_EOI, 1); - if (retval != ACK) - return -EIO; - - *result = send_command(board, USB_GPIB_READ_DATA, 0); - - DIA_LOG(1, "done with %x\n", *result); - - retval = set_control_line(board, IB_BUS_EOI, 0); - if (retval != 0x06) - return -EIO; - - return 0; -} - -/* read */ - -static int usb_gpib_read(struct gpib_board *board, - u8 *buffer, - size_t length, - int *end, - size_t *bytes_read) -{ -#define MAX_READ_EXCESS 16384 - - struct char_buf b = {NULL, 0}; - - int retval; - char c, nc; - int ic; - struct timespec64 before, after; - int read_count = MAX_READ_EXCESS; - struct usb_gpib_priv *pd = (struct usb_gpib_priv *)board->private_data; - - DIA_LOG(1, "enter %p -> %zu\n", board, length); - - *bytes_read = 0; /* by default, things go wrong */ - *end = 0; - - set_timeout(board); - - /* single byte read has a special handling */ - - if (length == 1) { - char inbuf[2] = {0, 0}; - - /* read a single character */ - - ktime_get_real_ts64 (&before); - - retval = write_loop(GPIB_DEV, USB_GPIB_READ_1, strlen(USB_GPIB_READ_1)); - if (retval < 0) - return retval; - - retval = skel_do_read(GPIB_DEV, inbuf, 1); - retval += skel_do_read(GPIB_DEV, inbuf + 1, 1); - - ktime_get_real_ts64 (&after); - - DIA_LOG(1, "single read: %x %x %x in %d\n", retval, - inbuf[0], inbuf[1], - usec_diff(&after, &before)); - - /* good char / last char? */ - - if (retval == 2 && inbuf[1] == ACK) { - buffer[0] = inbuf[0]; - *bytes_read = 1; - return 0; - } - if (retval < 2) - return -EIO; - else - return -ETIME; - } - - /* allocate buffer for multibyte read */ - - b.inbuf = kmalloc(INBUF_SIZE, GFP_KERNEL); - if (!b.inbuf) - return -ENOMEM; - - /* send read command and check <DLE><STX> sequence */ - - retval = write_loop(GPIB_DEV, USB_GPIB_READ, strlen(USB_GPIB_READ)); - if (retval < 0) - goto read_return; - - if (one_char(board, &b) != DLE || one_char(board, &b) != STX) { - dev_err(board->gpib_dev, "wrong <DLE><STX> sequence\n"); - retval = -EIO; - goto read_return; - } - - /* get data flow */ - - while (1) { - ic = one_char(board, &b); - if (ic == -EIO) { - retval = -EIO; - goto read_return; - } - c = ic; - - if (c == DLE) - nc = one_char(board, &b); - if (c != DLE || nc == DLE) { - /* data byte - store into buffer */ - - if (*bytes_read == length) - break; /* data overflow */ - if (c == DLE) - c = nc; - buffer[(*bytes_read)++] = c; - if (c == pd->eos) { - *end = 1; - break; - } - - } else { - /* we are in the closing <DLE><ETX> sequence */ - c = nc; - if (c == ETX) { - c = one_char(board, &b); - if (c == ACK) { - *end = 1; - retval = 0; - goto read_return; - } else { - dev_err(board->gpib_dev, "wrong end of message %x", c); - retval = -ETIME; - goto read_return; - } - } else { - dev_err(board->gpib_dev, "lone <DLE> in stream"); - retval = -EIO; - goto read_return; - } - } - } - - /* we had a data overflow - flush excess data */ - - while (read_count--) { - if (one_char(board, &b) != DLE) - continue; - c = one_char(board, &b); - if (c == DLE) - continue; - if (c == ETX) { - c = one_char(board, &b); - if (c == ACK) { - if (MAX_READ_EXCESS - read_count > 1) - dev_dbg(board->gpib_dev, "small buffer - maybe some data lost"); - retval = 0; - goto read_return; - } - break; - } - } - - dev_err(board->gpib_dev, "no input end - board in odd state\n"); - retval = -EIO; - -read_return: - kfree(b.inbuf); - - DIA_LOG(1, "done with byte/status: %d %x %d\n", (int)*bytes_read, retval, *end); - - if (retval == 0 || retval == -ETIME) { - if (send_command(board, USB_GPIB_UNTALK, sizeof(USB_GPIB_UNTALK)) == 0x06) - return retval; - return -EIO; - } - - return retval; -} - -/* remote_enable */ - -static void usb_gpib_remote_enable(struct gpib_board *board, int enable) -{ - int retval; - - retval = set_control_line(board, IB_BUS_REN, enable ? 1 : 0); - if (retval != ACK) - dev_err(board->gpib_dev, "could not set REN line: %x\n", retval); - - DIA_LOG(1, "done with %x\n", retval); -} - -/* request_system_control */ - -static int usb_gpib_request_system_control(struct gpib_board *board, int request_control) -{ - if (!request_control) - return -EINVAL; - - DIA_LOG(1, "done with %d -> %lx\n", request_control, board->status); - return 0; -} - -/* take_control */ -/* beware: the sync flag is ignored; what is its real meaning? */ - -static int usb_gpib_take_control(struct gpib_board *board, int sync) -{ - int retval; - - retval = set_control_line(board, IB_BUS_ATN, 1); - - DIA_LOG(1, "done with %d %x\n", sync, retval); - - if (retval == ACK) - return 0; - return -EIO; -} - -/* update_status */ - -static unsigned int usb_gpib_update_status(struct gpib_board *board, - unsigned int clear_mask) -{ - /* There is nothing we can do here, I guess */ - - board->status &= ~clear_mask; - - DIA_LOG(1, "done with %x %lx\n", clear_mask, board->status); - - return board->status; -} - -/* write */ -/* beware: DLE characters are not escaped - can only send ASCII data */ - -static int usb_gpib_write(struct gpib_board *board, - u8 *buffer, - size_t length, - int send_eoi, - size_t *bytes_written) -{ - int retval; - char *msg; - - DIA_LOG(1, "enter %p -> %zu\n", board, length); - - set_timeout(board); - - msg = kmalloc(length + 8, GFP_KERNEL); - if (!msg) - return -ENOMEM; - - memcpy(msg, "\nIB\020\002", 5); - memcpy(msg + 5, buffer, length); - memcpy(msg + 5 + length, "\020\003\n", 3); - - retval = send_command(board, msg, length + 8); - kfree(msg); - - DIA_LOG(1, "<%.*s> -> %x\n", (int)length, buffer, retval); - - if (retval != ACK) - return -EPIPE; - - *bytes_written = length; - - if (send_command(board, USB_GPIB_UNLISTEN, sizeof(USB_GPIB_UNLISTEN)) != 0x06) - return -EPIPE; - - return length; -} - -/* - * *** following functions not implemented yet *** - */ - -/* parallel_poll configure */ - -static void usb_gpib_parallel_poll_configure(struct gpib_board *board, - u8 configuration) -{ -} - -/* parallel_poll_response */ - -static void usb_gpib_parallel_poll_response(struct gpib_board *board, int ist) -{ -} - -/* primary_address */ - -static int usb_gpib_primary_address(struct gpib_board *board, unsigned int address) -{ - return 0; -} - -/* return_to_local */ - -static void usb_gpib_return_to_local(struct gpib_board *board) -{ -} - -/* secondary_address */ - -static int usb_gpib_secondary_address(struct gpib_board *board, - unsigned int address, - int enable) -{ - return 0; -} - -/* serial_poll_response */ - -static void usb_gpib_serial_poll_response(struct gpib_board *board, u8 status) -{ -} - -/* serial_poll_status */ - -static u8 usb_gpib_serial_poll_status(struct gpib_board *board) -{ - return 0; -} - -/* t1_delay */ - -static int usb_gpib_t1_delay(struct gpib_board *board, unsigned int nano_sec) -{ - return 0; -} - -/* - * *** module dispatch table and init/exit functions *** - */ - -static struct gpib_interface usb_gpib_interface = { - .name = NAME, - .attach = usb_gpib_attach, - .detach = usb_gpib_detach, - .read = usb_gpib_read, - .write = usb_gpib_write, - .command = usb_gpib_command, - .take_control = usb_gpib_take_control, - .go_to_standby = usb_gpib_go_to_standby, - .request_system_control = usb_gpib_request_system_control, - .interface_clear = usb_gpib_interface_clear, - .remote_enable = usb_gpib_remote_enable, - .enable_eos = usb_gpib_enable_eos, - .disable_eos = usb_gpib_disable_eos, - .parallel_poll = usb_gpib_parallel_poll, - .parallel_poll_configure = usb_gpib_parallel_poll_configure, - .parallel_poll_response = usb_gpib_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = usb_gpib_line_status, - .update_status = usb_gpib_update_status, - .primary_address = usb_gpib_primary_address, - .secondary_address = usb_gpib_secondary_address, - .serial_poll_response = usb_gpib_serial_poll_response, - .serial_poll_status = usb_gpib_serial_poll_status, - .t1_delay = usb_gpib_t1_delay, - .return_to_local = usb_gpib_return_to_local, - .skip_check_for_command_acceptors = 1 -}; - -/* - * usb_gpib_init_module(), usb_gpib_exit_module() - * - * This functions are called every time a new device is detected - * and registered or is removed and unregistered. - * We must take note of created and destroyed usb minors to be used - * when usb_gpib_attach() and usb_gpib_detach() will be called on - * request by gpib_config. - */ - -static int usb_gpib_init_module(struct usb_interface *interface) -{ - int j, mask, rv; - - rv = mutex_lock_interruptible(&minors_lock); - if (rv < 0) - return rv; - - if (!assigned_usb_minors) { - rv = gpib_register_driver(&usb_gpib_interface, THIS_MODULE); - if (rv) { - pr_err("gpib_register_driver failed: error = %d\n", rv); - goto exit; - } - } else { - /* - * check if minor is already registered - maybe useless, but if - * it happens the code is inconsistent somewhere - */ - - for (j = 0 ; j < MAX_DEV ; j++) { - if (usb_minors[j] == interface->minor && assigned_usb_minors & 1 << j) { - pr_err("CODE BUG: USB minor %d registered at %d.\n", - interface->minor, j); - rv = -1; - goto exit; - } - } - } - - /* find a free slot */ - - for (j = 0 ; j < MAX_DEV ; j++) { - mask = 1 << j; - if ((assigned_usb_minors & mask) == 0) { - usb_minors[j] = interface->minor; - lpvo_usb_interfaces[j] = interface; - assigned_usb_minors |= mask; - rv = 0; - goto exit; - } - } - pr_err("No slot available for interface %p minor %d\n", interface, interface->minor); - rv = -1; - -exit: - mutex_unlock(&minors_lock); - return rv; -} - -static void usb_gpib_exit_module(int minor) -{ - int j; - - mutex_lock(&minors_lock); - for (j = 0 ; j < MAX_DEV ; j++) { - if (usb_minors[j] == minor && assigned_usb_minors & 1 << j) { - assigned_usb_minors &= ~(1 << j); - usb_minors[j] = -1; - if (assigned_usb_minors == 0) - gpib_unregister_driver(&usb_gpib_interface); - goto exit; - } - } - pr_err("CODE BUG: USB minor %d not found.\n", minor); - -exit: - mutex_unlock(&minors_lock); -} - -/* - * Default latency time (16 msec) is too long. - * We must use 1 msec (best); anyhow, no more than 5 msec. - * - * Defines and function taken and modified from the kernel tree - * (see ftdi_sio.h and ftdi_sio.c). - */ - -#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */ -#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER -#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40 -#define WDR_TIMEOUT 5000 /* default urb timeout */ -#define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */ - -#define LATENCY_TIMER 1 /* use a small latency timer: 1 ... 5 msec */ -#define LATENCY_CHANNEL 0 /* channel selection in multichannel devices */ -static int write_latency_timer(struct usb_device *udev) -{ - int rv = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - FTDI_SIO_SET_LATENCY_TIMER_REQUEST, - FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, - LATENCY_TIMER, LATENCY_CHANNEL, - NULL, 0, WDR_TIMEOUT); - if (rv < 0) - dev_err(&udev->dev, "Unable to write latency timer: %i\n", rv); - return rv; -} - -/***************************************************************************** - * * - * The following code is a modified version of the USB Skeleton driver * - * written by Greg Kroah-Hartman and available in the kernel tree. * - * * - * Functions skel_open() and skel_release() have been rewritten and named * - * skel_do_open() and skel_do_release() to process the attach and detach * - * requests coming from gpib_config. * - * * - * Functions skel_read() and skel_write() have been split into a * - * skel_do_read() and skel_do_write(), that cover the kernel stuff of read * - * and write operations, and the original skel_read() and skel_write(), * - * that handle communication with user space and call their _do_ companion. * - * * - * Only the _do_ versions are used by the lpvo_usb_gpib driver; other ones * - * can be (optionally) maintained in the compilation to have direct access * - * to a gpib controller for debug and diagnostics. * - * * - * To avoid collisions in names, devices in user space have been renamed * - * lpvo_raw1, lpvo_raw2 .... and the usb driver has been renamed with the * - * gpib module name. * - * * - *****************************************************************************/ - -/* - * USB Skeleton driver - 2.2 - * - * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) - * - * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c - * but has been rewritten to be easier to read and use. - */ - -#include <linux/errno.h> -#include <linux/kref.h> -#include <linux/uaccess.h> -#include <linux/mutex.h> - -/* Get a minor range for your devices from the usb maintainer */ -#define USB_SKEL_MINOR_BASE 192 - -/* private defines */ - -#define MAX_TRANSFER (PAGE_SIZE - 512) -/* - * MAX_TRANSFER is chosen so that the VM is not stressed by - * allocations > PAGE_SIZE and the number of packets in a page - * is an integer 512 is the largest possible packet on EHCI - */ - -#define WRITES_IN_FLIGHT 1 /* we do not want more than one pending write */ -#define USER_DEVICE 1 /* compile for device(s) in user space */ - -/* Structure to hold all of our device specific stuff */ -struct usb_skel { - struct usb_device *udev; /* the usb device for this device */ - struct usb_interface *interface; /* the interface for this device */ - struct semaphore limit_sem; /* limiting the number of writes in progress */ - struct usb_anchor submitted; /* in case need to retract our submissions */ - struct urb *bulk_in_urb; /* the urb to read data with */ - unsigned char *bulk_in_buffer; /* the buffer to receive data */ - size_t bulk_in_size; /* the size of the receive buffer */ - size_t bulk_in_filled; /* number of bytes in the buffer */ - size_t bulk_in_copied; /* already copied to user space */ - __u8 bulk_in_endpoint_addr; /* the address of the bulk in endpoint */ - __u8 bulk_out_endpoint_addr; /* the address of the bulk out endpoint */ - int errors; /* the last request tanked */ - bool ongoing_read; /* a read is going on */ - spinlock_t err_lock; /* lock for errors */ - struct kref kref; - struct mutex io_mutex; /* synchronize I/O with disconnect */ - wait_queue_head_t bulk_in_wait; /* to wait for an ongoing read */ -}; - -#define to_skel_dev(d) container_of(d, struct usb_skel, kref) - -static struct usb_driver skel_driver; -static void skel_draw_down(struct usb_skel *dev); - -static void skel_delete(struct kref *kref) -{ - struct usb_skel *dev = to_skel_dev(kref); - - usb_free_urb(dev->bulk_in_urb); - usb_put_dev(dev->udev); - kfree(dev->bulk_in_buffer); - kfree(dev); -} - -/* - * skel_do_open() - to be called by usb_gpib_attach - */ - -static int skel_do_open(struct gpib_board *board, int subminor) -{ - struct usb_skel *dev; - struct usb_interface *interface; - int retval = 0; - - interface = usb_find_interface(&skel_driver, subminor); - if (!interface) { - dev_err(board->gpib_dev, "can't find device for minor %d\n", subminor); - retval = -ENODEV; - goto exit; - } - - dev = usb_get_intfdata(interface); - if (!dev) { - retval = -ENODEV; - goto exit; - } - - retval = usb_autopm_get_interface(interface); - if (retval) - goto exit; - - /* increment our usage count for the device */ - kref_get(&dev->kref); - - /* save our object in the file's private structure */ - GPIB_DEV = dev; - -exit: - return retval; -} - -/* - * skel_do_release() - to be called by usb_gpib_detach - */ - -static int skel_do_release(struct gpib_board *board) -{ - struct usb_skel *dev; - - dev = GPIB_DEV; - if (!dev) - return -ENODEV; - - /* allow the device to be autosuspended */ - mutex_lock(&dev->io_mutex); - if (dev->interface) - usb_autopm_put_interface(dev->interface); - mutex_unlock(&dev->io_mutex); - - /* decrement the count on our device */ - kref_put(&dev->kref, skel_delete); - return 0; -} - -/* - * read functions - */ - -static void skel_read_bulk_callback(struct urb *urb) -{ - struct usb_skel *dev; - unsigned long flags; - - dev = urb->context; - - spin_lock_irqsave(&dev->err_lock, flags); - /* sync/async unlink faults aren't errors */ - if (urb->status) { - if (!(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN)) - dev_err(&dev->interface->dev, "nonzero read bulk status received: %d\n", - urb->status); - - dev->errors = urb->status; - } else { - dev->bulk_in_filled = urb->actual_length; - } - dev->ongoing_read = 0; - spin_unlock_irqrestore(&dev->err_lock, flags); - - wake_up_interruptible(&dev->bulk_in_wait); -} - -static int skel_do_read_io(struct usb_skel *dev, size_t count) -{ - int rv; - - /* prepare a read */ - usb_fill_bulk_urb(dev->bulk_in_urb, - dev->udev, - usb_rcvbulkpipe(dev->udev, - dev->bulk_in_endpoint_addr), - dev->bulk_in_buffer, - min(dev->bulk_in_size, count), - skel_read_bulk_callback, - dev); - /* tell everybody to leave the URB alone */ - spin_lock_irq(&dev->err_lock); - dev->ongoing_read = 1; - spin_unlock_irq(&dev->err_lock); - - /* submit bulk in urb, which means no data to deliver */ - dev->bulk_in_filled = 0; - dev->bulk_in_copied = 0; - - /* do it */ - rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL); - if (rv < 0) { - dev_err(&dev->interface->dev, "failed submitting read urb, error %d\n", rv); - rv = (rv == -ENOMEM) ? rv : -EIO; - spin_lock_irq(&dev->err_lock); - dev->ongoing_read = 0; - spin_unlock_irq(&dev->err_lock); - } - - return rv; -} - -/* - * skel_do_read() - read operations from lpvo_usb_gpib - */ - -static ssize_t skel_do_read(struct usb_skel *dev, char *buffer, size_t count) -{ - int rv; - bool ongoing_io; - - /* if we cannot read at all, return EOF */ - - if (!dev->bulk_in_urb || !count) - return 0; - -restart: /* added to comply with ftdi timeout technique */ - - /* no concurrent readers */ - - rv = mutex_lock_interruptible(&dev->io_mutex); - if (rv < 0) - return rv; - - if (!dev->interface) { /* disconnect() was called */ - rv = -ENODEV; - goto exit; - } - -retry: - /* if IO is under way, we must not touch things */ - spin_lock_irq(&dev->err_lock); - ongoing_io = dev->ongoing_read; - spin_unlock_irq(&dev->err_lock); - - if (ongoing_io) { -// /* nonblocking IO shall not wait */ -// /* no file, no O_NONBLOCK; maybe provide when from user space */ -// if (file->f_flags & O_NONBLOCK) { -// rv = -EAGAIN; -// goto exit; -// } - - /* - * IO may take forever - * hence wait in an interruptible state - */ - rv = wait_event_interruptible(dev->bulk_in_wait, (!dev->ongoing_read)); - if (rv < 0) - goto exit; - } - - /* errors must be reported */ - rv = dev->errors; - if (rv < 0) { - /* any error is reported once */ - dev->errors = 0; - /* to preserve notifications about reset */ - rv = (rv == -EPIPE) ? rv : -EIO; - /* report it */ - goto exit; - } - - /* - * if the buffer is filled we may satisfy the read - * else we need to start IO - */ - - if (dev->bulk_in_filled) { - /* we had read data */ - - size_t available = dev->bulk_in_filled - dev->bulk_in_copied; -// size_t chunk = min(available, count); /* compute chunk later */ - size_t chunk; - - if (!available) { - /* - * all data has been used - * actual IO needs to be done - */ - /* - * it seems that requests for less than dev->bulk_in_size - * are not accepted - */ - rv = skel_do_read_io(dev, dev->bulk_in_size); - if (rv < 0) - goto exit; - else - goto retry; - } - - /* - * data is available - chunk tells us how much shall be copied - */ - - /* - * Condition dev->bulk_in_copied > 0 maybe will never happen. In case, - * signal the event and copy using the original procedure, i.e., copy - * first two bytes also - */ - - if (dev->bulk_in_copied) { - chunk = min(available, count); - memcpy(buffer, dev->bulk_in_buffer + dev->bulk_in_copied, chunk); - rv = chunk; - dev->bulk_in_copied += chunk; - - /* copy discarding first two bytes that contain ftdi chip status */ - - } else { - /* account for two bytes to be discarded */ - chunk = min(available, count + 2); - if (chunk < 2) { - dev_err(&dev->udev->dev, "BAD READ - chunk: %zu\n", chunk); - rv = -EIO; - goto exit; - } - - memcpy(buffer, dev->bulk_in_buffer + 2, chunk - 2); - rv = chunk; - dev->bulk_in_copied += chunk; - } - - /* - * if we are asked for more than we have, - * we start IO but don't wait - * - * No, no read ahead allowed; if the case, more data will be - * asked for by the lpvo_usb_gpib layer. - */ -// if (available < count) -// skel_do_read_io(dev, dev->bulk_in_size); - } else { - /* no data in the buffer */ - rv = skel_do_read_io(dev, dev->bulk_in_size); - if (rv < 0) - goto exit; - else - goto retry; - } -exit: - mutex_unlock(&dev->io_mutex); - if (rv == 2) - goto restart; /* ftdi chip returns two status bytes after a latency anyhow */ - - if (rv > 0) - return rv - 2; /* account for 2 discarded bytes in a valid buffer */ - return rv; -} - -/* - * write functions - */ - -static void skel_write_bulk_callback(struct urb *urb) -{ - struct usb_skel *dev; - unsigned long flags; - - dev = urb->context; - - /* sync/async unlink faults aren't errors */ - if (urb->status) { - if (!(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN)) - dev_err(&dev->interface->dev, - "nonzero write bulk status received: %d\n", urb->status); - - spin_lock_irqsave(&dev->err_lock, flags); - dev->errors = urb->status; - spin_unlock_irqrestore(&dev->err_lock, flags); - } - - /* free up our allocated buffer */ - usb_free_coherent(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); - up(&dev->limit_sem); -} - -/* - * skel_do_write() - write operations from lpvo_usb_gpib - */ - -static ssize_t skel_do_write(struct usb_skel *dev, const char *buffer, size_t count) -{ - int retval = 0; - struct urb *urb = NULL; - char *buf = NULL; - size_t writesize = min_t(size_t, count, (size_t)MAX_TRANSFER); - - /* verify that we actually have some data to write */ - if (count == 0) - goto exit; - - /* - * limit the number of URBs in flight to stop a user from using up all - * RAM - */ - /* Only one URB is used, because we can't have a pending write() and go on */ - -// if (!(file->f_flags & O_NONBLOCK)) { /* no NONBLOCK provided */ - if (down_interruptible(&dev->limit_sem)) { - retval = -ERESTARTSYS; - goto exit; - } -// } else { -// if (down_trylock(&dev->limit_sem)) { -// retval = -EAGAIN; -// goto exit; -// } -// } - - spin_lock_irq(&dev->err_lock); - retval = dev->errors; - if (retval < 0) { - /* any error is reported once */ - dev->errors = 0; - /* to preserve notifications about reset */ - retval = (retval == -EPIPE) ? retval : -EIO; - } - spin_unlock_irq(&dev->err_lock); - if (retval < 0) - goto error; - - /* create a urb, and a buffer for it, and copy the data to the urb */ - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - retval = -ENOMEM; - goto error; - } - - buf = usb_alloc_coherent(dev->udev, writesize, GFP_KERNEL, - &urb->transfer_dma); - if (!buf) { - retval = -ENOMEM; - goto error; - } - - memcpy(buf, buffer, count); - - /* this lock makes sure we don't submit URBs to gone devices */ - mutex_lock(&dev->io_mutex); - if (!dev->interface) { /* disconnect() was called */ - mutex_unlock(&dev->io_mutex); - retval = -ENODEV; - goto error; - } - - /* initialize the urb properly */ - usb_fill_bulk_urb(urb, dev->udev, - usb_sndbulkpipe(dev->udev, dev->bulk_out_endpoint_addr), - buf, writesize, skel_write_bulk_callback, dev); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - usb_anchor_urb(urb, &dev->submitted); - - /* send the data out the bulk port */ - retval = usb_submit_urb(urb, GFP_KERNEL); - mutex_unlock(&dev->io_mutex); - if (retval) { - dev_err(&dev->interface->dev, "failed submitting write urb, error %d\n", retval); - goto error_unanchor; - } - - /* - * release our reference to this urb, the USB core will eventually free - * it entirely - */ - usb_free_urb(urb); - - return writesize; - -error_unanchor: - usb_unanchor_urb(urb); -error: - if (urb) { - usb_free_coherent(dev->udev, writesize, buf, urb->transfer_dma); - usb_free_urb(urb); - } - up(&dev->limit_sem); - -exit: - return retval; -} - -/* - * services for the user space devices - */ - -#if USER_DEVICE /* conditional compilation of user space device */ - -static int skel_flush(struct file *file, fl_owner_t id) -{ - struct usb_skel *dev; - int res; - - dev = file->private_data; - if (!dev) - return -ENODEV; - - /* wait for io to stop */ - mutex_lock(&dev->io_mutex); - skel_draw_down(dev); - - /* read out errors, leave subsequent opens a clean slate */ - spin_lock_irq(&dev->err_lock); - res = dev->errors ? (dev->errors == -EPIPE ? -EPIPE : -EIO) : 0; - dev->errors = 0; - spin_unlock_irq(&dev->err_lock); - - mutex_unlock(&dev->io_mutex); - - return res; -} - -static int skel_open(struct inode *inode, struct file *file) -{ - struct usb_skel *dev; - struct usb_interface *interface; - int subminor; - int retval = 0; - - subminor = iminor(inode); - - interface = usb_find_interface(&skel_driver, subminor); - if (!interface) { - pr_err("can't find device for minor %d\n", subminor); - retval = -ENODEV; - goto exit; - } - - dev = usb_get_intfdata(interface); - if (!dev) { - retval = -ENODEV; - goto exit; - } - - retval = usb_autopm_get_interface(interface); - if (retval) - goto exit; - - /* increment our usage count for the device */ - kref_get(&dev->kref); - - /* save our object in the file's private structure */ - file->private_data = dev; - -exit: - return retval; -} - -static int skel_release(struct inode *inode, struct file *file) -{ - struct usb_skel *dev; - - dev = file->private_data; - if (!dev) - return -ENODEV; - - /* allow the device to be autosuspended */ - mutex_lock(&dev->io_mutex); - if (dev->interface) - usb_autopm_put_interface(dev->interface); - mutex_unlock(&dev->io_mutex); - - /* decrement the count on our device */ - kref_put(&dev->kref, skel_delete); - return 0; -} - -/* - * user space access to read function - */ - -static ssize_t skel_read(struct file *file, char __user *buffer, size_t count, - loff_t *ppos) -{ - struct usb_skel *dev; - char *buf; - ssize_t rv; - - dev = file->private_data; - - buf = kmalloc(count, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - rv = skel_do_read(dev, buf, count); - - if (rv > 0) { - if (copy_to_user(buffer, buf, rv)) { - kfree(buf); - return -EFAULT; - } - } - kfree(buf); - return rv; -} - -/* - * user space access to write function - */ - -static ssize_t skel_write(struct file *file, const char __user *user_buffer, - size_t count, loff_t *ppos) -{ - struct usb_skel *dev; - char *buf; - ssize_t rv; - - dev = file->private_data; - - buf = kmalloc(count, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, user_buffer, count)) { - kfree(buf); - return -EFAULT; - } - - rv = skel_do_write(dev, buf, count); - kfree(buf); - return rv; -} -#endif - -static const struct file_operations skel_fops = { - .owner = THIS_MODULE, -#if USER_DEVICE - .read = skel_read, - .write = skel_write, - .open = skel_open, - .release = skel_release, - .flush = skel_flush, - .llseek = noop_llseek, -#endif -}; - -/* - * usb class driver info in order to get a minor number from the usb core, - * and to have the device registered with the driver core - */ -#if USER_DEVICE -static struct usb_class_driver skel_class = { - .name = "lpvo_raw%d", - .fops = &skel_fops, - .minor_base = USB_SKEL_MINOR_BASE, -}; -#endif - -static int skel_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_skel *dev; - struct usb_endpoint_descriptor *bulk_in, *bulk_out; - int retval; - char *device_path; - - mutex_init(&minors_lock); /* required for handling minor numbers table */ - - /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - kref_init(&dev->kref); - sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); - mutex_init(&dev->io_mutex); - spin_lock_init(&dev->err_lock); - init_usb_anchor(&dev->submitted); - init_waitqueue_head(&dev->bulk_in_wait); - - dev->udev = usb_get_dev(interface_to_usbdev(interface)); - dev->interface = interface; - - /* set up the endpoint information */ - /* use only the first bulk-in and bulk-out endpoints */ - retval = usb_find_common_endpoints(interface->cur_altsetting, - &bulk_in, &bulk_out, NULL, NULL); - if (retval) { - dev_err(&interface->dev, - "Could not find both bulk-in and bulk-out endpoints\n"); - goto error; - } - - dev->bulk_in_size = usb_endpoint_maxp(bulk_in); - dev->bulk_in_endpoint_addr = bulk_in->bEndpointAddress; - dev->bulk_in_buffer = kmalloc(dev->bulk_in_size, GFP_KERNEL); - if (!dev->bulk_in_buffer) { - retval = -ENOMEM; - goto error; - } - dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->bulk_in_urb) { - retval = -ENOMEM; - goto error; - } - - dev->bulk_out_endpoint_addr = bulk_out->bEndpointAddress; - - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, dev); - - /* let the world know */ - - device_path = kobject_get_path(&dev->udev->dev.kobj, GFP_KERNEL); - dev_dbg(&interface->dev, "New lpvo_usb_device -> bus: %d dev: %d path: %s\n", - dev->udev->bus->busnum, dev->udev->devnum, device_path); - kfree(device_path); - -#if USER_DEVICE - /* we can register the device now, as it is ready */ - retval = usb_register_dev(interface, &skel_class); - if (retval) { - /* something prevented us from registering this driver */ - dev_err(&interface->dev, - "Not able to get a minor for this device.\n"); - usb_set_intfdata(interface, NULL); - goto error; - } -#endif - - write_latency_timer(dev->udev); /* adjust the latency timer */ - - usb_gpib_init_module(interface); /* last, init the lpvo for this minor */ - - return 0; - -error: - /* this frees allocated memory */ - kref_put(&dev->kref, skel_delete); - - return retval; -} - -static void skel_disconnect(struct usb_interface *interface) -{ - struct usb_skel *dev; - int minor = interface->minor; - - usb_gpib_exit_module(minor); /* first, disactivate the lpvo */ - - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - -#if USER_DEVICE - /* give back our minor */ - usb_deregister_dev(interface, &skel_class); -#endif - - /* prevent more I/O from starting */ - mutex_lock(&dev->io_mutex); - dev->interface = NULL; - mutex_unlock(&dev->io_mutex); - - usb_kill_anchored_urbs(&dev->submitted); - - /* decrement our usage count */ - kref_put(&dev->kref, skel_delete); -} - -static void skel_draw_down(struct usb_skel *dev) -{ - int time; - - time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000); - if (!time) - usb_kill_anchored_urbs(&dev->submitted); - usb_kill_urb(dev->bulk_in_urb); -} - -static int skel_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct usb_skel *dev = usb_get_intfdata(intf); - - if (!dev) - return 0; - skel_draw_down(dev); - return 0; -} - -static int skel_resume(struct usb_interface *intf) -{ - return 0; -} - -static int skel_pre_reset(struct usb_interface *intf) -{ - struct usb_skel *dev = usb_get_intfdata(intf); - - mutex_lock(&dev->io_mutex); - skel_draw_down(dev); - - return 0; -} - -static int skel_post_reset(struct usb_interface *intf) -{ - struct usb_skel *dev = usb_get_intfdata(intf); - - /* we are sure no URBs are active - no locking needed */ - dev->errors = -EPIPE; - mutex_unlock(&dev->io_mutex); - - return 0; -} - -static struct usb_driver skel_driver = { - .name = NAME, - .probe = skel_probe, - .disconnect = skel_disconnect, - .suspend = skel_suspend, - .resume = skel_resume, - .pre_reset = skel_pre_reset, - .post_reset = skel_post_reset, - .id_table = skel_table, - .supports_autosuspend = 1, -}; - -module_usb_driver(skel_driver); diff --git a/drivers/staging/gpib/nec7210/Makefile b/drivers/staging/gpib/nec7210/Makefile deleted file mode 100644 index 64330f2e89d1..000000000000 --- a/drivers/staging/gpib/nec7210/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -obj-$(CONFIG_GPIB_NEC7210) += nec7210.o - - diff --git a/drivers/staging/gpib/nec7210/board.h b/drivers/staging/gpib/nec7210/board.h deleted file mode 100644 index ac3fe38ade57..000000000000 --- a/drivers/staging/gpib/nec7210/board.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2001, 2002 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _GPIB_PCIIA_BOARD_H -#define _GPIB_PCIIA_BOARD_H - -#include "gpibP.h" -#include <linux/io.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/delay.h> - -#include "nec7210.h" - -#endif //_GPIB_PCIIA_BOARD_H - diff --git a/drivers/staging/gpib/nec7210/nec7210.c b/drivers/staging/gpib/nec7210/nec7210.c deleted file mode 100644 index bbf39367f5e4..000000000000 --- a/drivers/staging/gpib/nec7210/nec7210.c +++ /dev/null @@ -1,1121 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * copyright : (C) 2001, 2002 by Frank Mori Hess - ***************************************************************************/ - -#define dev_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include "board.h" -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <asm/dma.h> -#include <linux/bitops.h> -#include <linux/pci.h> -#include <linux/pci_ids.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/delay.h> - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB library code for NEC uPD7210"); - -int nec7210_enable_eos(struct gpib_board *board, struct nec7210_priv *priv, u8 eos_byte, - int compare_8_bits) -{ - write_byte(priv, eos_byte, EOSR); - priv->auxa_bits |= HR_REOS; - if (compare_8_bits) - priv->auxa_bits |= HR_BIN; - else - priv->auxa_bits &= ~HR_BIN; - write_byte(priv, priv->auxa_bits, AUXMR); - return 0; -} -EXPORT_SYMBOL(nec7210_enable_eos); - -void nec7210_disable_eos(struct gpib_board *board, struct nec7210_priv *priv) -{ - priv->auxa_bits &= ~HR_REOS; - write_byte(priv, priv->auxa_bits, AUXMR); -} -EXPORT_SYMBOL(nec7210_disable_eos); - -int nec7210_parallel_poll(struct gpib_board *board, struct nec7210_priv *priv, u8 *result) -{ - int ret; - - clear_bit(COMMAND_READY_BN, &priv->state); - - // execute parallel poll - write_byte(priv, AUX_EPP, AUXMR); - // wait for result FIXME: support timeouts - ret = wait_event_interruptible(board->wait, test_bit(COMMAND_READY_BN, &priv->state)); - if (ret) { - dev_dbg(board->gpib_dev, "gpib: parallel poll interrupted\n"); - return -ERESTARTSYS; - } - *result = read_byte(priv, CPTR); - - return 0; -} -EXPORT_SYMBOL(nec7210_parallel_poll); - -void nec7210_parallel_poll_configure(struct gpib_board *board, - struct nec7210_priv *priv, unsigned int configuration) -{ - write_byte(priv, PPR | configuration, AUXMR); -} -EXPORT_SYMBOL(nec7210_parallel_poll_configure); - -void nec7210_parallel_poll_response(struct gpib_board *board, struct nec7210_priv *priv, int ist) -{ - if (ist) - write_byte(priv, AUX_SPPF, AUXMR); - else - write_byte(priv, AUX_CPPF, AUXMR); -} -EXPORT_SYMBOL(nec7210_parallel_poll_response); -/* - * This is really only adequate for chips that do a 488.2 style reqt/reqf - * based on bit 6 of the SPMR (see chapter 11.3.3 of 488.2). For simpler chips that simply - * set rsv directly based on bit 6, we either need to do more hardware setup to expose - * the 488.2 capability (for example with NI chips), or we need to implement the - * 488.2 set srv state machine in the driver (if that is even viable). - */ -void nec7210_serial_poll_response(struct gpib_board *board, - struct nec7210_priv *priv, u8 status) -{ - unsigned long flags; - - spin_lock_irqsave(&board->spinlock, flags); - if (status & request_service_bit) { - priv->srq_pending = 1; - clear_bit(SPOLL_NUM, &board->status); - - } else { - priv->srq_pending = 0; - } - write_byte(priv, status, SPMR); - spin_unlock_irqrestore(&board->spinlock, flags); -} -EXPORT_SYMBOL(nec7210_serial_poll_response); - -u8 nec7210_serial_poll_status(struct gpib_board *board, struct nec7210_priv *priv) -{ - return read_byte(priv, SPSR); -} -EXPORT_SYMBOL(nec7210_serial_poll_status); - -int nec7210_primary_address(const struct gpib_board *board, struct nec7210_priv *priv, - unsigned int address) -{ - // put primary address in address0 - write_byte(priv, address & ADDRESS_MASK, ADR); - return 0; -} -EXPORT_SYMBOL(nec7210_primary_address); - -int nec7210_secondary_address(const struct gpib_board *board, struct nec7210_priv *priv, - unsigned int address, int enable) -{ - if (enable) { - // put secondary address in address1 - write_byte(priv, HR_ARS | (address & ADDRESS_MASK), ADR); - // go to address mode 2 - priv->reg_bits[ADMR] &= ~HR_ADM0; - priv->reg_bits[ADMR] |= HR_ADM1; - } else { - // disable address1 register - write_byte(priv, HR_ARS | HR_DT | HR_DL, ADR); - // go to address mode 1 - priv->reg_bits[ADMR] |= HR_ADM0; - priv->reg_bits[ADMR] &= ~HR_ADM1; - } - write_byte(priv, priv->reg_bits[ADMR], ADMR); - return 0; -} -EXPORT_SYMBOL(nec7210_secondary_address); - -static void update_talker_state(struct nec7210_priv *priv, unsigned int address_status_bits) -{ - if ((address_status_bits & HR_TA)) { - if ((address_status_bits & HR_NATN)) { - if (address_status_bits & HR_SPMS) - priv->talker_state = serial_poll_active; - else - priv->talker_state = talker_active; - } else { - priv->talker_state = talker_addressed; - } - } else { - priv->talker_state = talker_idle; - } -} - -static void update_listener_state(struct nec7210_priv *priv, unsigned int address_status_bits) -{ - if (address_status_bits & HR_LA) { - if ((address_status_bits & HR_NATN)) - priv->listener_state = listener_active; - else - priv->listener_state = listener_addressed; - } else { - priv->listener_state = listener_idle; - } -} - -unsigned int nec7210_update_status_nolock(struct gpib_board *board, struct nec7210_priv *priv) -{ - int address_status_bits; - u8 spoll_status; - - if (!priv) - return 0; - - address_status_bits = read_byte(priv, ADSR); - if (address_status_bits & HR_CIC) - set_bit(CIC_NUM, &board->status); - else - clear_bit(CIC_NUM, &board->status); - // check for talker/listener addressed - update_talker_state(priv, address_status_bits); - if (priv->talker_state == talker_active || priv->talker_state == talker_addressed) - set_bit(TACS_NUM, &board->status); - else - clear_bit(TACS_NUM, &board->status); - update_listener_state(priv, address_status_bits); - if (priv->listener_state == listener_active || - priv->listener_state == listener_addressed) - set_bit(LACS_NUM, &board->status); - else - clear_bit(LACS_NUM, &board->status); - if (address_status_bits & HR_NATN) - clear_bit(ATN_NUM, &board->status); - else - set_bit(ATN_NUM, &board->status); - spoll_status = nec7210_serial_poll_status(board, priv); - if (priv->srq_pending && (spoll_status & request_service_bit) == 0) { - priv->srq_pending = 0; - set_bit(SPOLL_NUM, &board->status); - } - - /* - * we rely on the interrupt handler to set the - * rest of the status bits - */ - - return board->status; -} -EXPORT_SYMBOL(nec7210_update_status_nolock); - -unsigned int nec7210_update_status(struct gpib_board *board, struct nec7210_priv *priv, - unsigned int clear_mask) -{ - unsigned long flags; - unsigned int retval; - - spin_lock_irqsave(&board->spinlock, flags); - board->status &= ~clear_mask; - retval = nec7210_update_status_nolock(board, priv); - spin_unlock_irqrestore(&board->spinlock, flags); - - return retval; -} -EXPORT_SYMBOL(nec7210_update_status); - -unsigned int nec7210_set_reg_bits(struct nec7210_priv *priv, unsigned int reg, - unsigned int mask, unsigned int bits) -{ - priv->reg_bits[reg] &= ~mask; - priv->reg_bits[reg] |= mask & bits; - write_byte(priv, priv->reg_bits[reg], reg); - return priv->reg_bits[reg]; -} -EXPORT_SYMBOL(nec7210_set_reg_bits); - -void nec7210_set_handshake_mode(struct gpib_board *board, struct nec7210_priv *priv, int mode) -{ - unsigned long flags; - - mode &= HR_HANDSHAKE_MASK; - - spin_lock_irqsave(&board->spinlock, flags); - if ((priv->auxa_bits & HR_HANDSHAKE_MASK) != mode) { - priv->auxa_bits &= ~HR_HANDSHAKE_MASK; - priv->auxa_bits |= mode; - write_byte(priv, priv->auxa_bits, AUXMR); - } - spin_unlock_irqrestore(&board->spinlock, flags); -} -EXPORT_SYMBOL(nec7210_set_handshake_mode); - -u8 nec7210_read_data_in(struct gpib_board *board, struct nec7210_priv *priv, int *end) -{ - unsigned long flags; - u8 data; - - spin_lock_irqsave(&board->spinlock, flags); - data = read_byte(priv, DIR); - clear_bit(READ_READY_BN, &priv->state); - if (test_and_clear_bit(RECEIVED_END_BN, &priv->state)) - *end = 1; - else - *end = 0; - spin_unlock_irqrestore(&board->spinlock, flags); - - return data; -} -EXPORT_SYMBOL(nec7210_read_data_in); - -int nec7210_take_control(struct gpib_board *board, struct nec7210_priv *priv, int syncronous) -{ - int i; - const int timeout = 100; - int retval = 0; - unsigned int adsr_bits = 0; - - if (syncronous) - write_byte(priv, AUX_TCS, AUXMR); - else - write_byte(priv, AUX_TCA, AUXMR); - // busy wait until ATN is asserted - for (i = 0; i < timeout; i++) { - adsr_bits = read_byte(priv, ADSR); - if ((adsr_bits & HR_NATN) == 0) - break; - udelay(1); - } - if (i == timeout) - return -ETIMEDOUT; - - clear_bit(WRITE_READY_BN, &priv->state); - - return retval; -} -EXPORT_SYMBOL(nec7210_take_control); - -int nec7210_go_to_standby(struct gpib_board *board, struct nec7210_priv *priv) -{ - int i; - const int timeout = 1000; - unsigned int adsr_bits = 0; - int retval = 0; - - write_byte(priv, AUX_GTS, AUXMR); - // busy wait until ATN is released - for (i = 0; i < timeout; i++) { - adsr_bits = read_byte(priv, ADSR); - if (adsr_bits & HR_NATN) - break; - udelay(1); - } - // if busy wait has failed, try sleeping - if (i == timeout) { - for (i = 0; i < HZ; i++) { - set_current_state(TASK_INTERRUPTIBLE); - if (schedule_timeout(1)) - return -ERESTARTSYS; - adsr_bits = read_byte(priv, ADSR); - if (adsr_bits & HR_NATN) - break; - } - if (i == HZ) - return -ETIMEDOUT; - } - - clear_bit(COMMAND_READY_BN, &priv->state); - return retval; -} -EXPORT_SYMBOL(nec7210_go_to_standby); - -int nec7210_request_system_control(struct gpib_board *board, struct nec7210_priv *priv, - int request_control) -{ - if (request_control == 0) { - write_byte(priv, AUX_CREN, AUXMR); - write_byte(priv, AUX_CIFC, AUXMR); - write_byte(priv, AUX_DSC, AUXMR); - } - return 0; -} -EXPORT_SYMBOL(nec7210_request_system_control); - -void nec7210_interface_clear(struct gpib_board *board, struct nec7210_priv *priv, int assert) -{ - if (assert) - write_byte(priv, AUX_SIFC, AUXMR); - else - write_byte(priv, AUX_CIFC, AUXMR); -} -EXPORT_SYMBOL(nec7210_interface_clear); - -void nec7210_remote_enable(struct gpib_board *board, struct nec7210_priv *priv, int enable) -{ - if (enable) - write_byte(priv, AUX_SREN, AUXMR); - else - write_byte(priv, AUX_CREN, AUXMR); -} -EXPORT_SYMBOL(nec7210_remote_enable); - -void nec7210_release_rfd_holdoff(struct gpib_board *board, struct nec7210_priv *priv) -{ - unsigned long flags; - - spin_lock_irqsave(&board->spinlock, flags); - if (test_bit(RFD_HOLDOFF_BN, &priv->state) && - test_bit(READ_READY_BN, &priv->state) == 0) { - write_byte(priv, AUX_FH, AUXMR); - clear_bit(RFD_HOLDOFF_BN, &priv->state); - } - spin_unlock_irqrestore(&board->spinlock, flags); -} -EXPORT_SYMBOL(nec7210_release_rfd_holdoff); - -int nec7210_t1_delay(struct gpib_board *board, struct nec7210_priv *priv, - unsigned int nano_sec) -{ - unsigned int retval; - - if (nano_sec <= 500) { - priv->auxb_bits |= HR_TRI; - retval = 500; - } else { - priv->auxb_bits &= ~HR_TRI; - retval = 2000; - } - write_byte(priv, priv->auxb_bits, AUXMR); - - return retval; -} -EXPORT_SYMBOL(nec7210_t1_delay); - -void nec7210_return_to_local(const struct gpib_board *board, struct nec7210_priv *priv) -{ - write_byte(priv, AUX_RTL, AUXMR); -} -EXPORT_SYMBOL(nec7210_return_to_local); - -static inline short nec7210_atn_has_changed(struct gpib_board *board, struct nec7210_priv *priv) -{ - short address_status_bits = read_byte(priv, ADSR); - - if (address_status_bits & HR_NATN) { - if (test_bit(ATN_NUM, &board->status)) - return 1; - else - return 0; - } else { - if (test_bit(ATN_NUM, &board->status)) - return 0; - else - return 1; - } - return -1; -} - -int nec7210_command(struct gpib_board *board, struct nec7210_priv *priv, u8 - *buffer, size_t length, size_t *bytes_written) -{ - int retval = 0; - unsigned long flags; - - *bytes_written = 0; - - clear_bit(BUS_ERROR_BN, &priv->state); - - while (*bytes_written < length) { - if (wait_event_interruptible(board->wait, - test_bit(COMMAND_READY_BN, &priv->state) || - test_bit(BUS_ERROR_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) { - dev_dbg(board->gpib_dev, "command wait interrupted\n"); - retval = -ERESTARTSYS; - break; - } - if (test_bit(TIMO_NUM, &board->status)) - break; - if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) - break; - spin_lock_irqsave(&board->spinlock, flags); - clear_bit(COMMAND_READY_BN, &priv->state); - write_byte(priv, buffer[*bytes_written], CDOR); - spin_unlock_irqrestore(&board->spinlock, flags); - - ++(*bytes_written); - - if (need_resched()) - schedule(); - } - // wait for last byte to get sent - if (wait_event_interruptible(board->wait, test_bit(COMMAND_READY_BN, &priv->state) || - test_bit(BUS_ERROR_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - - if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) - retval = -EIO; - - return retval; -} -EXPORT_SYMBOL(nec7210_command); - -static int pio_read(struct gpib_board *board, struct nec7210_priv *priv, u8 *buffer, - size_t length, int *end, size_t *bytes_read) -{ - ssize_t retval = 0; - - *bytes_read = 0; - *end = 0; - - while (*bytes_read < length) { - if (wait_event_interruptible(board->wait, - test_bit(READ_READY_BN, &priv->state) || - test_bit(DEV_CLEAR_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) { - retval = -ERESTARTSYS; - break; - } - if (test_bit(READ_READY_BN, &priv->state)) { - if (*bytes_read == 0) { - /* - * We set the handshake mode here because we know - * no new bytes will arrive (it has already arrived - * and is awaiting being read out of the chip) while we are changing - * modes. This ensures we can reliably keep track - * of the holdoff state. - */ - nec7210_set_handshake_mode(board, priv, HR_HLDA); - } - buffer[(*bytes_read)++] = nec7210_read_data_in(board, priv, end); - if (*end) - break; - } - if (test_bit(TIMO_NUM, &board->status)) { - retval = -ETIMEDOUT; - break; - } - if (test_bit(DEV_CLEAR_BN, &priv->state)) { - retval = -EINTR; - break; - } - - if (*bytes_read < length) - nec7210_release_rfd_holdoff(board, priv); - - if (need_resched()) - schedule(); - } - return retval; -} - -#ifdef NEC_DMA -static ssize_t __dma_read(struct gpib_board *board, struct nec7210_priv *priv, size_t length) -{ - ssize_t retval = 0; - size_t count = 0; - unsigned long flags, dma_irq_flags; - - if (length == 0) - return 0; - - spin_lock_irqsave(&board->spinlock, flags); - - dma_irq_flags = claim_dma_lock(); - disable_dma(priv->dma_channel); - /* program dma controller */ - clear_dma_ff(priv->dma_channel); - set_dma_count(priv->dma_channel, length); - set_dma_addr(priv->dma_channel, priv->dma_buffer_addr); - set_dma_mode(priv->dma_channel, DMA_MODE_READ); - release_dma_lock(dma_irq_flags); - - enable_dma(priv->dma_channel); - - set_bit(DMA_READ_IN_PROGRESS_BN, &priv->state); - clear_bit(READ_READY_BN, &priv->state); - - // enable nec7210 dma - nec7210_set_reg_bits(priv, IMR2, HR_DMAI, HR_DMAI); - - spin_unlock_irqrestore(&board->spinlock, flags); - - // wait for data to transfer - if (wait_event_interruptible(board->wait, - test_bit(DMA_READ_IN_PROGRESS_BN, &priv->state) == 0 || - test_bit(DEV_CLEAR_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_bit(DEV_CLEAR_BN, &priv->state)) - retval = -EINTR; - - // disable nec7210 dma - nec7210_set_reg_bits(priv, IMR2, HR_DMAI, 0); - - // record how many bytes we transferred - flags = claim_dma_lock(); - clear_dma_ff(priv->dma_channel); - disable_dma(priv->dma_channel); - count += length - get_dma_residue(priv->dma_channel); - release_dma_lock(flags); - - return retval ? retval : count; -} - -static ssize_t dma_read(struct gpib_board *board, struct nec7210_priv *priv, u8 *buffer, - size_t length) -{ - size_t remain = length; - size_t transfer_size; - ssize_t retval = 0; - - while (remain > 0) { - transfer_size = (priv->dma_buffer_length < remain) ? - priv->dma_buffer_length : remain; - retval = __dma_read(board, priv, transfer_size); - if (retval < 0) - break; - memcpy(buffer, priv->dma_buffer, transfer_size); - remain -= retval; - buffer += retval; - if (test_bit(RECEIVED_END_BN, &priv->state)) - break; - } - - if (retval < 0) - return retval; - - return length - remain; -} -#endif - -int nec7210_read(struct gpib_board *board, struct nec7210_priv *priv, u8 *buffer, - size_t length, int *end, size_t *bytes_read) -{ - ssize_t retval = 0; - - *end = 0; - *bytes_read = 0; - - if (length == 0) - return 0; - - clear_bit(DEV_CLEAR_BN, &priv->state); // XXX wrong - - nec7210_release_rfd_holdoff(board, priv); - - retval = pio_read(board, priv, buffer, length, end, bytes_read); - - return retval; -} -EXPORT_SYMBOL(nec7210_read); - -static int pio_write_wait(struct gpib_board *board, struct nec7210_priv *priv, - short wake_on_lacs, short wake_on_atn, short wake_on_bus_error) -{ - // wait until byte is ready to be sent - if (wait_event_interruptible(board->wait, - (test_bit(TACS_NUM, &board->status) && - test_bit(WRITE_READY_BN, &priv->state)) || - test_bit(DEV_CLEAR_BN, &priv->state) || - (wake_on_bus_error && test_bit(BUS_ERROR_BN, &priv->state)) || - (wake_on_lacs && test_bit(LACS_NUM, &board->status)) || - (wake_on_atn && test_bit(ATN_NUM, &board->status)) || - test_bit(TIMO_NUM, &board->status))) - return -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - return -ETIMEDOUT; - - if (test_bit(DEV_CLEAR_BN, &priv->state)) - return -EINTR; - - if (wake_on_bus_error && test_and_clear_bit(BUS_ERROR_BN, &priv->state)) - return -EIO; - - return 0; -} - -static int pio_write(struct gpib_board *board, struct nec7210_priv *priv, u8 *buffer, - size_t length, size_t *bytes_written) -{ - size_t last_count = 0; - ssize_t retval = 0; - unsigned long flags; - const int max_bus_errors = (length > 1000) ? length : 1000; - int bus_error_count = 0; - *bytes_written = 0; - - clear_bit(BUS_ERROR_BN, &priv->state); - - while (*bytes_written < length) { - if (need_resched()) - schedule(); - - retval = pio_write_wait(board, priv, 0, 0, priv->type == NEC7210); - if (retval == -EIO) { - /* resend last byte on bus error */ - *bytes_written = last_count; - /* - * we can get unrecoverable bus errors, - * so give up after a while - */ - bus_error_count++; - if (bus_error_count > max_bus_errors) - return retval; - continue; - } else { - if (retval < 0) - return retval; - } - spin_lock_irqsave(&board->spinlock, flags); - clear_bit(BUS_ERROR_BN, &priv->state); - clear_bit(WRITE_READY_BN, &priv->state); - last_count = *bytes_written; - write_byte(priv, buffer[(*bytes_written)++], CDOR); - spin_unlock_irqrestore(&board->spinlock, flags); - } - retval = pio_write_wait(board, priv, 1, 1, priv->type == NEC7210); - return retval; -} - -#ifdef NEC_DMA -static ssize_t __dma_write(struct gpib_board *board, struct nec7210_priv *priv, dma_addr_t address, - size_t length) -{ - unsigned long flags, dma_irq_flags; - int residue = 0; - int retval = 0; - - spin_lock_irqsave(&board->spinlock, flags); - - /* program dma controller */ - dma_irq_flags = claim_dma_lock(); - disable_dma(priv->dma_channel); - clear_dma_ff(priv->dma_channel); - set_dma_count(priv->dma_channel, length); - set_dma_addr(priv->dma_channel, address); - set_dma_mode(priv->dma_channel, DMA_MODE_WRITE); - enable_dma(priv->dma_channel); - release_dma_lock(dma_irq_flags); - - // enable board's dma for output - nec7210_set_reg_bits(priv, IMR2, HR_DMAO, HR_DMAO); - - clear_bit(WRITE_READY_BN, &priv->state); - set_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state); - - spin_unlock_irqrestore(&board->spinlock, flags); - - // suspend until message is sent - if (wait_event_interruptible(board->wait, - test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state) == 0 || - test_bit(BUS_ERROR_BN, &priv->state) || - test_bit(DEV_CLEAR_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_and_clear_bit(DEV_CLEAR_BN, &priv->state)) - retval = -EINTR; - if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) - retval = -EIO; - - // disable board's dma - nec7210_set_reg_bits(priv, IMR2, HR_DMAO, 0); - - dma_irq_flags = claim_dma_lock(); - clear_dma_ff(priv->dma_channel); - disable_dma(priv->dma_channel); - residue = get_dma_residue(priv->dma_channel); - release_dma_lock(dma_irq_flags); - - if (residue) - retval = -EPIPE; - - return retval ? retval : length; -} - -static ssize_t dma_write(struct gpib_board *board, struct nec7210_priv *priv, u8 *buffer, - size_t length) -{ - size_t remain = length; - size_t transfer_size; - ssize_t retval = 0; - - while (remain > 0) { - transfer_size = (priv->dma_buffer_length < remain) ? - priv->dma_buffer_length : remain; - memcpy(priv->dma_buffer, buffer, transfer_size); - retval = __dma_write(board, priv, priv->dma_buffer_addr, transfer_size); - if (retval < 0) - break; - remain -= retval; - buffer += retval; - } - - if (retval < 0) - return retval; - - return length - remain; -} -#endif -int nec7210_write(struct gpib_board *board, struct nec7210_priv *priv, - u8 *buffer, size_t length, int send_eoi, - size_t *bytes_written) -{ - int retval = 0; - - *bytes_written = 0; - - clear_bit(DEV_CLEAR_BN, &priv->state); // XXX - - if (send_eoi) - length-- ; // save the last byte for sending EOI - - if (length > 0) { - // isa dma transfer - if (0 /*priv->dma_channel*/) { -/* - * dma writes are unreliable since they can't recover from bus errors - * (which happen when ATN is asserted in the middle of a write) - */ -#ifdef NEC_DMA - retval = dma_write(board, priv, buffer, length); - if (retval < 0) - return retval; - count += retval; -#endif - } else { // PIO transfer - size_t num_bytes; - - retval = pio_write(board, priv, buffer, length, &num_bytes); - - *bytes_written += num_bytes; - if (retval < 0) - return retval; - } - } - if (send_eoi) { - size_t num_bytes; - - /* - * We need to wait to make sure we will immediately be able to write the data byte - * into the chip before sending the associated AUX_SEOI command. This is really - * only needed for length==1 since otherwise the earlier calls to pio_write - * will have dont the wait already. - */ - retval = pio_write_wait(board, priv, 0, 0, priv->type == NEC7210); - if (retval < 0) - return retval; - /*send EOI */ - write_byte(priv, AUX_SEOI, AUXMR); - - retval = pio_write(board, priv, &buffer[*bytes_written], 1, &num_bytes); - *bytes_written += num_bytes; - if (retval < 0) - return retval; - } - - return retval; -} -EXPORT_SYMBOL(nec7210_write); - -/* - * interrupt service routine - */ -irqreturn_t nec7210_interrupt(struct gpib_board *board, struct nec7210_priv *priv) -{ - int status1, status2; - - // read interrupt status (also clears status) - status1 = read_byte(priv, ISR1); - status2 = read_byte(priv, ISR2); - - return nec7210_interrupt_have_status(board, priv, status1, status2); -} -EXPORT_SYMBOL(nec7210_interrupt); - -irqreturn_t nec7210_interrupt_have_status(struct gpib_board *board, - struct nec7210_priv *priv, int status1, int status2) -{ -#ifdef NEC_DMA - unsigned long dma_flags; -#endif - int retval = IRQ_NONE; - - // record service request in status - if (status2 & HR_SRQI) - set_bit(SRQI_NUM, &board->status); - - // change in lockout status - if (status2 & HR_LOKC) { - if (status2 & HR_LOK) - set_bit(LOK_NUM, &board->status); - else - clear_bit(LOK_NUM, &board->status); - } - - // change in remote status - if (status2 & HR_REMC) { - if (status2 & HR_REM) - set_bit(REM_NUM, &board->status); - else - clear_bit(REM_NUM, &board->status); - } - - // record reception of END - if (status1 & HR_END) { - set_bit(RECEIVED_END_BN, &priv->state); - if ((priv->auxa_bits & HR_HANDSHAKE_MASK) == HR_HLDE) - set_bit(RFD_HOLDOFF_BN, &priv->state); - } - - // get incoming data in PIO mode - if ((status1 & HR_DI)) { - set_bit(READ_READY_BN, &priv->state); - if ((priv->auxa_bits & HR_HANDSHAKE_MASK) == HR_HLDA) - set_bit(RFD_HOLDOFF_BN, &priv->state); - } -#ifdef NEC_DMA - // check for dma read transfer complete - if (test_bit(DMA_READ_IN_PROGRESS_BN, &priv->state)) { - dma_flags = claim_dma_lock(); - disable_dma(priv->dma_channel); - clear_dma_ff(priv->dma_channel); - if ((status1 & HR_END) || get_dma_residue(priv->dma_channel) == 0) - clear_bit(DMA_READ_IN_PROGRESS_BN, &priv->state); - else - enable_dma(priv->dma_channel); - release_dma_lock(dma_flags); - } -#endif - if ((status1 & HR_DO)) { - if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state) == 0) - set_bit(WRITE_READY_BN, &priv->state); -#ifdef NEC_DMA - if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state)) { // write data, isa dma mode - // check if dma transfer is complete - dma_flags = claim_dma_lock(); - disable_dma(priv->dma_channel); - clear_dma_ff(priv->dma_channel); - if (get_dma_residue(priv->dma_channel) == 0) { - clear_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state); - // XXX race? byte may still be in CDOR reg - } else { - clear_bit(WRITE_READY_BN, &priv->state); - enable_dma(priv->dma_channel); - } - release_dma_lock(dma_flags); - } -#endif - } - - // outgoing command can be sent - if (status2 & HR_CO) - set_bit(COMMAND_READY_BN, &priv->state); - - // command pass through received - if (status1 & HR_CPT) - write_byte(priv, AUX_NVAL, AUXMR); - - if (status1 & HR_ERR) - set_bit(BUS_ERROR_BN, &priv->state); - - if (status1 & HR_DEC) { - unsigned short address_status_bits = read_byte(priv, ADSR); - - // ignore device clear events if we are controller in charge - if ((address_status_bits & HR_CIC) == 0) { - push_gpib_event(board, EVENT_DEV_CLR); - set_bit(DEV_CLEAR_BN, &priv->state); - } - } - - if (status1 & HR_DET) - push_gpib_event(board, EVENT_DEV_TRG); - - // Addressing status has changed - if (status2 & HR_ADSC) - set_bit(ADR_CHANGE_BN, &priv->state); - - if ((status1 & priv->reg_bits[IMR1]) || - (status2 & (priv->reg_bits[IMR2] & IMR2_ENABLE_INTR_MASK)) || - nec7210_atn_has_changed(board, priv)) { - nec7210_update_status_nolock(board, priv); - dev_dbg(board->gpib_dev, "minor %i, stat %lx, isr1 0x%x, imr1 0x%x, isr2 0x%x, imr2 0x%x\n", - board->minor, board->status, status1, priv->reg_bits[IMR1], status2, - priv->reg_bits[IMR2]); - wake_up_interruptible(&board->wait); /* wake up sleeping process */ - retval = IRQ_HANDLED; - } - - return retval; -} -EXPORT_SYMBOL(nec7210_interrupt_have_status); - -void nec7210_board_reset(struct nec7210_priv *priv, const struct gpib_board *board) -{ - /* 7210 chip reset */ - write_byte(priv, AUX_CR, AUXMR); - - /* disable all interrupts */ - priv->reg_bits[IMR1] = 0; - write_byte(priv, priv->reg_bits[IMR1], IMR1); - priv->reg_bits[IMR2] = 0; - write_byte(priv, priv->reg_bits[IMR2], IMR2); - write_byte(priv, 0, SPMR); - - /* clear registers by reading */ - read_byte(priv, CPTR); - read_byte(priv, ISR1); - read_byte(priv, ISR2); - - /* parallel poll unconfigure */ - write_byte(priv, PPR | HR_PPU, AUXMR); - - priv->reg_bits[ADMR] = HR_TRM0 | HR_TRM1; - - priv->auxa_bits = AUXRA | HR_HLDA; - write_byte(priv, priv->auxa_bits, AUXMR); - - write_byte(priv, AUXRE | 0, AUXMR); - - /* set INT pin to active high, enable command pass through of unknown commands */ - priv->auxb_bits = AUXRB | HR_CPTE; - write_byte(priv, priv->auxb_bits, AUXMR); - write_byte(priv, AUXRE, AUXMR); -} -EXPORT_SYMBOL(nec7210_board_reset); - -void nec7210_board_online(struct nec7210_priv *priv, const struct gpib_board *board) -{ - /* set GPIB address */ - nec7210_primary_address(board, priv, board->pad); - nec7210_secondary_address(board, priv, board->sad, board->sad >= 0); - - /* enable interrupts */ - priv->reg_bits[IMR1] = HR_ERRIE | HR_DECIE | HR_ENDIE | - HR_DETIE | HR_CPTIE | HR_DOIE | HR_DIIE; - priv->reg_bits[IMR2] = IMR2_ENABLE_INTR_MASK; - write_byte(priv, priv->reg_bits[IMR1], IMR1); - write_byte(priv, priv->reg_bits[IMR2], IMR2); - - write_byte(priv, AUX_PON, AUXMR); -} -EXPORT_SYMBOL(nec7210_board_online); - -#ifdef CONFIG_HAS_IOPORT -/* wrappers for io */ -u8 nec7210_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num) -{ - return inb(priv->iobase + register_num * priv->offset); -} -EXPORT_SYMBOL(nec7210_ioport_read_byte); - -void nec7210_ioport_write_byte(struct nec7210_priv *priv, u8 data, unsigned int register_num) -{ - if (register_num == AUXMR) - /* - * locking makes absolutely sure noone accesses the - * AUXMR register faster than once per microsecond - */ - nec7210_locking_ioport_write_byte(priv, data, register_num); - else - outb(data, priv->iobase + register_num * priv->offset); -} -EXPORT_SYMBOL(nec7210_ioport_write_byte); - -/* locking variants of io wrappers, for chips that page-in registers */ -u8 nec7210_locking_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num) -{ - u8 retval; - unsigned long flags; - - spin_lock_irqsave(&priv->register_page_lock, flags); - retval = inb(priv->iobase + register_num * priv->offset); - spin_unlock_irqrestore(&priv->register_page_lock, flags); - return retval; -} -EXPORT_SYMBOL(nec7210_locking_ioport_read_byte); - -void nec7210_locking_ioport_write_byte(struct nec7210_priv *priv, u8 data, - unsigned int register_num) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->register_page_lock, flags); - if (register_num == AUXMR) - udelay(1); - outb(data, priv->iobase + register_num * priv->offset); - spin_unlock_irqrestore(&priv->register_page_lock, flags); -} -EXPORT_SYMBOL(nec7210_locking_ioport_write_byte); -#endif - -u8 nec7210_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num) -{ - return readb(priv->mmiobase + register_num * priv->offset); -} -EXPORT_SYMBOL(nec7210_iomem_read_byte); - -void nec7210_iomem_write_byte(struct nec7210_priv *priv, u8 data, unsigned int register_num) -{ - if (register_num == AUXMR) - /* - * locking makes absolutely sure noone accesses the - * AUXMR register faster than once per microsecond - */ - nec7210_locking_iomem_write_byte(priv, data, register_num); - else - writeb(data, priv->mmiobase + register_num * priv->offset); -} -EXPORT_SYMBOL(nec7210_iomem_write_byte); - -u8 nec7210_locking_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num) -{ - u8 retval; - unsigned long flags; - - spin_lock_irqsave(&priv->register_page_lock, flags); - retval = readb(priv->mmiobase + register_num * priv->offset); - spin_unlock_irqrestore(&priv->register_page_lock, flags); - return retval; -} -EXPORT_SYMBOL(nec7210_locking_iomem_read_byte); - -void nec7210_locking_iomem_write_byte(struct nec7210_priv *priv, u8 data, - unsigned int register_num) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->register_page_lock, flags); - if (register_num == AUXMR) - udelay(1); - writeb(data, priv->mmiobase + register_num * priv->offset); - spin_unlock_irqrestore(&priv->register_page_lock, flags); -} -EXPORT_SYMBOL(nec7210_locking_iomem_write_byte); - -static int __init nec7210_init_module(void) -{ - return 0; -} - -static void __exit nec7210_exit_module(void) -{ -} - -module_init(nec7210_init_module); -module_exit(nec7210_exit_module); diff --git a/drivers/staging/gpib/ni_usb/Makefile b/drivers/staging/gpib/ni_usb/Makefile deleted file mode 100644 index 469c5d16add3..000000000000 --- a/drivers/staging/gpib/ni_usb/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -obj-$(CONFIG_GPIB_NI_USB) += ni_usb_gpib.o - - diff --git a/drivers/staging/gpib/ni_usb/ni_usb_gpib.c b/drivers/staging/gpib/ni_usb/ni_usb_gpib.c deleted file mode 100644 index 1f8412de9fa3..000000000000 --- a/drivers/staging/gpib/ni_usb/ni_usb_gpib.c +++ /dev/null @@ -1,2678 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * driver for National Instruments usb to gpib adapters - * copyright : (C) 2004 by Frank Mori Hess - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define DRV_NAME KBUILD_MODNAME - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include "ni_usb_gpib.h" -#include "gpibP.h" -#include "nec7210.h" -#include "tnt4882_registers.h" - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB driver for National Instruments USB devices"); - -#define MAX_NUM_NI_USB_INTERFACES 128 -static struct usb_interface *ni_usb_driver_interfaces[MAX_NUM_NI_USB_INTERFACES]; - -static int ni_usb_parse_status_block(const u8 *buffer, struct ni_usb_status_block *status); -static int ni_usb_set_interrupt_monitor(struct gpib_board *board, unsigned int monitored_bits); -static void ni_usb_stop(struct ni_usb_priv *ni_priv); - -static DEFINE_MUTEX(ni_usb_hotplug_lock); - -// calculates a reasonable timeout in that can be passed to usb functions -static inline unsigned long ni_usb_timeout_msecs(unsigned int usec) -{ - if (usec == 0) - return 0; - return 2000 + usec / 500; -}; - -// returns timeout code byte for use in ni-usb-b instructions -static unsigned short ni_usb_timeout_code(unsigned int usec) -{ - if (usec == 0) - return 0xf0; - else if (usec <= 10) - return 0xf1; - else if (usec <= 30) - return 0xf2; - else if (usec <= 100) - return 0xf3; - else if (usec <= 300) - return 0xf4; - else if (usec <= 1000) - return 0xf5; - else if (usec <= 3000) - return 0xf6; - else if (usec <= 10000) - return 0xf7; - else if (usec <= 30000) - return 0xf8; - else if (usec <= 100000) - return 0xf9; - else if (usec <= 300000) - return 0xfa; - else if (usec <= 1000000) - return 0xfb; - else if (usec <= 3000000) - return 0xfc; - else if (usec <= 10000000) - return 0xfd; - else if (usec <= 30000000) - return 0xfe; - else if (usec <= 100000000) - return 0xff; - else if (usec <= 300000000) - return 0x01; - /* - * NI driver actually uses 0xff for timeout T1000s, which is a bug in their code. - * I've verified on a usb-b that a code of 0x2 is correct for a 1000 sec timeout - */ - else if (usec <= 1000000000) - return 0x02; - pr_err("bug? usec is greater than 1e9\n"); - return 0xf0; -} - -static void ni_usb_bulk_complete(struct urb *urb) -{ - struct ni_usb_urb_ctx *context = urb->context; - - complete(&context->complete); -} - -static void ni_usb_timeout_handler(struct timer_list *t) -{ - struct ni_usb_priv *ni_priv = timer_container_of(ni_priv, t, - bulk_timer); - struct ni_usb_urb_ctx *context = &ni_priv->context; - - context->timed_out = 1; - complete(&context->complete); -}; - -// I'm using nonblocking loosely here, it only means -EAGAIN can be returned in certain cases -static int ni_usb_nonblocking_send_bulk_msg(struct ni_usb_priv *ni_priv, void *data, - int data_length, int *actual_data_length, - int timeout_msecs) -{ - struct usb_device *usb_dev; - int retval; - unsigned int out_pipe; - struct ni_usb_urb_ctx *context = &ni_priv->context; - - *actual_data_length = 0; - mutex_lock(&ni_priv->bulk_transfer_lock); - if (!ni_priv->bus_interface) { - mutex_unlock(&ni_priv->bulk_transfer_lock); - return -ENODEV; - } - if (ni_priv->bulk_urb) { - mutex_unlock(&ni_priv->bulk_transfer_lock); - return -EAGAIN; - } - ni_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ni_priv->bulk_urb) { - mutex_unlock(&ni_priv->bulk_transfer_lock); - return -ENOMEM; - } - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - out_pipe = usb_sndbulkpipe(usb_dev, ni_priv->bulk_out_endpoint); - init_completion(&context->complete); - context->timed_out = 0; - usb_fill_bulk_urb(ni_priv->bulk_urb, usb_dev, out_pipe, data, data_length, - &ni_usb_bulk_complete, context); - - if (timeout_msecs) - mod_timer(&ni_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs)); - - retval = usb_submit_urb(ni_priv->bulk_urb, GFP_KERNEL); - if (retval) { - timer_delete_sync(&ni_priv->bulk_timer); - usb_free_urb(ni_priv->bulk_urb); - ni_priv->bulk_urb = NULL; - dev_err(&usb_dev->dev, "failed to submit bulk out urb, retval=%i\n", - retval); - mutex_unlock(&ni_priv->bulk_transfer_lock); - return retval; - } - mutex_unlock(&ni_priv->bulk_transfer_lock); - wait_for_completion(&context->complete); // wait for ni_usb_bulk_complete - if (context->timed_out) { - usb_kill_urb(ni_priv->bulk_urb); - dev_err(&usb_dev->dev, "killed urb due to timeout\n"); - retval = -ETIMEDOUT; - } else { - retval = ni_priv->bulk_urb->status; - } - - timer_delete_sync(&ni_priv->bulk_timer); - *actual_data_length = ni_priv->bulk_urb->actual_length; - mutex_lock(&ni_priv->bulk_transfer_lock); - usb_free_urb(ni_priv->bulk_urb); - ni_priv->bulk_urb = NULL; - mutex_unlock(&ni_priv->bulk_transfer_lock); - return retval; -} - -static int ni_usb_send_bulk_msg(struct ni_usb_priv *ni_priv, void *data, int data_length, - int *actual_data_length, int timeout_msecs) -{ - int retval; - int timeout_msecs_remaining = timeout_msecs; - - retval = ni_usb_nonblocking_send_bulk_msg(ni_priv, data, data_length, actual_data_length, - timeout_msecs_remaining); - while (retval == -EAGAIN && (timeout_msecs == 0 || timeout_msecs_remaining > 0)) { - usleep_range(1000, 1500); - retval = ni_usb_nonblocking_send_bulk_msg(ni_priv, data, data_length, - actual_data_length, - timeout_msecs_remaining); - if (timeout_msecs != 0) - --timeout_msecs_remaining; - } - if (timeout_msecs != 0 && timeout_msecs_remaining <= 0) - return -ETIMEDOUT; - return retval; -} - -// I'm using nonblocking loosely here, it only means -EAGAIN can be returned in certain cases -static int ni_usb_nonblocking_receive_bulk_msg(struct ni_usb_priv *ni_priv, - void *data, int data_length, - int *actual_data_length, int timeout_msecs, - int interruptible) -{ - struct usb_device *usb_dev; - int retval; - unsigned int in_pipe; - struct ni_usb_urb_ctx *context = &ni_priv->context; - - *actual_data_length = 0; - mutex_lock(&ni_priv->bulk_transfer_lock); - if (!ni_priv->bus_interface) { - mutex_unlock(&ni_priv->bulk_transfer_lock); - return -ENODEV; - } - if (ni_priv->bulk_urb) { - mutex_unlock(&ni_priv->bulk_transfer_lock); - return -EAGAIN; - } - ni_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ni_priv->bulk_urb) { - mutex_unlock(&ni_priv->bulk_transfer_lock); - return -ENOMEM; - } - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - in_pipe = usb_rcvbulkpipe(usb_dev, ni_priv->bulk_in_endpoint); - init_completion(&context->complete); - context->timed_out = 0; - usb_fill_bulk_urb(ni_priv->bulk_urb, usb_dev, in_pipe, data, data_length, - &ni_usb_bulk_complete, context); - - if (timeout_msecs) - mod_timer(&ni_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs)); - - retval = usb_submit_urb(ni_priv->bulk_urb, GFP_KERNEL); - if (retval) { - timer_delete_sync(&ni_priv->bulk_timer); - usb_free_urb(ni_priv->bulk_urb); - ni_priv->bulk_urb = NULL; - dev_err(&usb_dev->dev, "failed to submit bulk in urb, retval=%i\n", retval); - mutex_unlock(&ni_priv->bulk_transfer_lock); - return retval; - } - mutex_unlock(&ni_priv->bulk_transfer_lock); - if (interruptible) { - if (wait_for_completion_interruptible(&context->complete)) { - /* - * If we got interrupted by a signal while - * waiting for the usb gpib to respond, we - * should send a stop command so it will - * finish up with whatever it was doing and - * send its response now. - */ - ni_usb_stop(ni_priv); - retval = -ERESTARTSYS; - /* - * now do an uninterruptible wait, it shouldn't take long - * for the board to respond now. - */ - wait_for_completion(&context->complete); - } - } else { - wait_for_completion(&context->complete); - } - if (context->timed_out) { - usb_kill_urb(ni_priv->bulk_urb); - dev_err(&usb_dev->dev, "killed urb due to timeout\n"); - retval = -ETIMEDOUT; - } else { - if (ni_priv->bulk_urb->status) - retval = ni_priv->bulk_urb->status; - } - timer_delete_sync(&ni_priv->bulk_timer); - *actual_data_length = ni_priv->bulk_urb->actual_length; - mutex_lock(&ni_priv->bulk_transfer_lock); - usb_free_urb(ni_priv->bulk_urb); - ni_priv->bulk_urb = NULL; - mutex_unlock(&ni_priv->bulk_transfer_lock); - return retval; -} - -static int ni_usb_receive_bulk_msg(struct ni_usb_priv *ni_priv, void *data, - int data_length, int *actual_data_length, int timeout_msecs, - int interruptible) -{ - int retval; - int timeout_msecs_remaining = timeout_msecs; - - retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, data, data_length, - actual_data_length, timeout_msecs_remaining, - interruptible); - while (retval == -EAGAIN && (timeout_msecs == 0 || timeout_msecs_remaining > 0)) { - usleep_range(1000, 1500); - retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, data, data_length, - actual_data_length, - timeout_msecs_remaining, - interruptible); - if (timeout_msecs != 0) - --timeout_msecs_remaining; - } - if (timeout_msecs && timeout_msecs_remaining <= 0) - return -ETIMEDOUT; - return retval; -} - -static int ni_usb_receive_control_msg(struct ni_usb_priv *ni_priv, __u8 request, - __u8 requesttype, __u16 value, __u16 index, - void *data, __u16 size, int timeout_msecs) -{ - struct usb_device *usb_dev; - int retval; - unsigned int in_pipe; - - mutex_lock(&ni_priv->control_transfer_lock); - if (!ni_priv->bus_interface) { - mutex_unlock(&ni_priv->control_transfer_lock); - return -ENODEV; - } - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - in_pipe = usb_rcvctrlpipe(usb_dev, 0); - retval = usb_control_msg(usb_dev, in_pipe, request, requesttype, value, index, data, - size, timeout_msecs); - mutex_unlock(&ni_priv->control_transfer_lock); - return retval; -} - -static void ni_usb_soft_update_status(struct gpib_board *board, unsigned int ni_usb_ibsta, - unsigned int clear_mask) -{ - static const unsigned int ni_usb_ibsta_mask = SRQI | ATN | CIC | REM | LACS | TACS | LOK; - - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); - unsigned int need_monitoring_bits = ni_usb_ibsta_monitor_mask; - unsigned long flags; - - board->status &= ~clear_mask; - board->status &= ~ni_usb_ibsta_mask; - board->status |= ni_usb_ibsta & ni_usb_ibsta_mask; - if (ni_usb_ibsta & DCAS) - push_gpib_event(board, EVENT_DEV_CLR); - if (ni_usb_ibsta & DTAS) - push_gpib_event(board, EVENT_DEV_TRG); - - spin_lock_irqsave(&board->spinlock, flags); -/* remove set status bits from monitored set why ?***/ - ni_priv->monitored_ibsta_bits &= ~ni_usb_ibsta; - need_monitoring_bits &= ~ni_priv->monitored_ibsta_bits; /* mm - monitored set */ - spin_unlock_irqrestore(&board->spinlock, flags); - dev_dbg(&usb_dev->dev, "need_monitoring_bits=0x%x\n", need_monitoring_bits); - - if (need_monitoring_bits & ~ni_usb_ibsta) - ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask); - else if (need_monitoring_bits & ni_usb_ibsta) - wake_up_interruptible(&board->wait); - - dev_dbg(&usb_dev->dev, "ibsta=0x%x\n", ni_usb_ibsta); -} - -static int ni_usb_parse_status_block(const u8 *buffer, struct ni_usb_status_block *status) -{ - u16 count; - - status->id = buffer[0]; - status->ibsta = (buffer[1] << 8) | buffer[2]; - status->error_code = buffer[3]; - count = buffer[4] | (buffer[5] << 8); - count = ~count; - count++; - status->count = count; - return 8; -}; - -static void ni_usb_dump_raw_block(const u8 *raw_data, int length) -{ - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 8, 1, raw_data, length, true); -} - -static int ni_usb_parse_register_read_block(const u8 *raw_data, unsigned int *results, - int num_results) -{ - int i = 0; - int j; - int unexpected = 0; - static const int results_per_chunk = 3; - - for (j = 0; j < num_results;) { - int k; - - if (raw_data[i++] != NIUSB_REGISTER_READ_DATA_START_ID) { - pr_err("parse error: wrong start id\n"); - unexpected = 1; - } - for (k = 0; k < results_per_chunk && j < num_results; ++k) - results[j++] = raw_data[i++]; - } - while (i % 4) - i++; - if (raw_data[i++] != NIUSB_REGISTER_READ_DATA_END_ID) { - pr_err("parse error: wrong end id\n"); - unexpected = 1; - } - if (raw_data[i++] % results_per_chunk != num_results % results_per_chunk) { - pr_err("parse error: wrong count=%i for NIUSB_REGISTER_READ_DATA_END\n", - (int)raw_data[i - 1]); - unexpected = 1; - } - while (i % 4) { - if (raw_data[i++] != 0) { - pr_err("unexpected data: raw_data[%i]=0x%x, expected 0\n", - i - 1, (int)raw_data[i - 1]); - unexpected = 1; - } - } - if (unexpected) - ni_usb_dump_raw_block(raw_data, i); - return i; -} - -static int ni_usb_parse_termination_block(const u8 *buffer) -{ - int i = 0; - - if (buffer[i++] != NIUSB_TERM_ID || - buffer[i++] != 0x0 || - buffer[i++] != 0x0 || - buffer[i++] != 0x0) { - pr_err("received unexpected termination block\n"); - pr_err(" expected: 0x%x 0x%x 0x%x 0x%x\n", NIUSB_TERM_ID, 0x0, 0x0, 0x0); - pr_err(" received: 0x%x 0x%x 0x%x 0x%x\n", - buffer[i - 4], buffer[i - 3], buffer[i - 2], buffer[i - 1]); - } - return i; -}; - -static int parse_board_ibrd_readback(const u8 *raw_data, struct ni_usb_status_block *status, - u8 *parsed_data, int parsed_data_length, - int *actual_bytes_read) -{ - static const int ibrd_data_block_length = 0xf; - static const int ibrd_extended_data_block_length = 0x1e; - int data_block_length = 0; - int i = 0; - int j = 0; - int k; - int num_data_blocks = 0; - struct ni_usb_status_block register_write_status; - int unexpected = 0; - - while (raw_data[i] == NIUSB_IBRD_DATA_ID || raw_data[i] == NIUSB_IBRD_EXTENDED_DATA_ID) { - if (raw_data[i] == NIUSB_IBRD_DATA_ID) { - data_block_length = ibrd_data_block_length; - } else if (raw_data[i] == NIUSB_IBRD_EXTENDED_DATA_ID) { - data_block_length = ibrd_extended_data_block_length; - if (raw_data[++i] != 0) { - pr_err("unexpected data: raw_data[%i]=0x%x, expected 0\n", - i, (int)raw_data[i]); - unexpected = 1; - } - } else { - pr_err("Unexpected NIUSB_IBRD ID\n"); - return -EINVAL; - } - ++i; - for (k = 0; k < data_block_length; k++) { - if (j < parsed_data_length) - parsed_data[j++] = raw_data[i++]; - else - ++i; - } - ++num_data_blocks; - } - i += ni_usb_parse_status_block(&raw_data[i], status); - if (status->id != NIUSB_IBRD_STATUS_ID) { - pr_err("bug: status->id=%i, != ibrd_status_id\n", status->id); - return -EIO; - } - i++; - if (num_data_blocks) { - *actual_bytes_read = (num_data_blocks - 1) * data_block_length + raw_data[i++]; - } else { - ++i; - *actual_bytes_read = 0; - } - if (*actual_bytes_read > j) - pr_err("bug: discarded data. actual_bytes_read=%i, j=%i\n", *actual_bytes_read, j); - for (k = 0; k < 2; k++) - if (raw_data[i++] != 0) { - pr_err("unexpected data: raw_data[%i]=0x%x, expected 0\n", - i - 1, (int)raw_data[i - 1]); - unexpected = 1; - } - i += ni_usb_parse_status_block(&raw_data[i], ®ister_write_status); - if (register_write_status.id != NIUSB_REG_WRITE_ID) { - pr_err("unexpected data: register write status id=0x%x, expected 0x%x\n", - register_write_status.id, NIUSB_REG_WRITE_ID); - unexpected = 1; - } - if (raw_data[i++] != 2) { - pr_err("unexpected data: register write count=%i, expected 2\n", - (int)raw_data[i - 1]); - unexpected = 1; - } - for (k = 0; k < 3; k++) - if (raw_data[i++] != 0) { - pr_err("unexpected data: raw_data[%i]=0x%x, expected 0\n", - i - 1, (int)raw_data[i - 1]); - unexpected = 1; - } - i += ni_usb_parse_termination_block(&raw_data[i]); - if (unexpected) - ni_usb_dump_raw_block(raw_data, i); - return i; -} - -static int ni_usb_parse_reg_write_status_block(const u8 *raw_data, - struct ni_usb_status_block *status, - int *writes_completed) -{ - int i = 0; - - i += ni_usb_parse_status_block(raw_data, status); - *writes_completed = raw_data[i++]; - while (i % 4) - i++; - return i; -} - -static int ni_usb_write_registers(struct ni_usb_priv *ni_priv, - const struct ni_usb_register *writes, int num_writes, - unsigned int *ibsta) -{ - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); - int retval; - u8 *out_data, *in_data; - int out_data_length; - static const int in_data_length = 0x20; - int bytes_written = 0, bytes_read = 0; - int i = 0; - int j; - struct ni_usb_status_block status; - static const int bytes_per_write = 3; - int reg_writes_completed; - - out_data_length = num_writes * bytes_per_write + 0x10; - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return -ENOMEM; - i += ni_usb_bulk_register_write_header(&out_data[i], num_writes); - for (j = 0; j < num_writes; j++) - i += ni_usb_bulk_register_write(&out_data[i], writes[j]); - while (i % 4) - out_data[i++] = 0x00; - i += ni_usb_bulk_termination(&out_data[i]); - - mutex_lock(&ni_priv->addressed_transfer_lock); - - retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); - kfree(out_data); - if (retval) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - retval, bytes_written, i); - return retval; - } - - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - return -ENOMEM; - } - retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0); - if (retval || bytes_read != 16) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", - retval, bytes_read); - ni_usb_dump_raw_block(in_data, bytes_read); - kfree(in_data); - return retval; - } - - mutex_unlock(&ni_priv->addressed_transfer_lock); - - ni_usb_parse_reg_write_status_block(in_data, &status, ®_writes_completed); - // FIXME parse extra 09 status bits and termination - kfree(in_data); - if (status.id != NIUSB_REG_WRITE_ID) { - dev_err(&usb_dev->dev, "parse error, id=0x%x != NIUSB_REG_WRITE_ID\n", status.id); - return -EIO; - } - if (status.error_code) { - dev_err(&usb_dev->dev, "nonzero error code 0x%x\n", status.error_code); - return -EIO; - } - if (reg_writes_completed != num_writes) { - dev_err(&usb_dev->dev, "reg_writes_completed=%i, num_writes=%i\n", - reg_writes_completed, num_writes); - return -EIO; - } - if (ibsta) - *ibsta = status.ibsta; - return 0; -} - -// interface functions -static int ni_usb_read(struct gpib_board *board, u8 *buffer, size_t length, - int *end, size_t *bytes_read) -{ - int retval, parse_retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - u8 *out_data, *in_data; - static const int out_data_length = 0x20; - int in_data_length; - int usb_bytes_written = 0, usb_bytes_read = 0; - int i = 0; - int complement_count; - int actual_length; - struct ni_usb_status_block status; - static const int max_read_length = 0xffff; - struct ni_usb_register reg; - - *bytes_read = 0; - if (!ni_priv->bus_interface) - return -ENODEV; - if (length > max_read_length) - return -EINVAL; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return -ENOMEM; - out_data[i++] = 0x0a; - out_data[i++] = ni_priv->eos_mode >> 8; - out_data[i++] = ni_priv->eos_char; - out_data[i++] = ni_usb_timeout_code(board->usec_timeout); - complement_count = length - 1; - complement_count = ~complement_count; - out_data[i++] = complement_count & 0xff; - out_data[i++] = (complement_count >> 8) & 0xff; - out_data[i++] = 0x0; - out_data[i++] = 0x0; - i += ni_usb_bulk_register_write_header(&out_data[i], 2); - reg.device = NIUSB_SUBDEV_TNT4882; - reg.address = nec7210_to_tnt4882_offset(AUXMR); - reg.value = AUX_HLDI; - i += ni_usb_bulk_register_write(&out_data[i], reg); - reg.value = AUX_CLEAR_END; - i += ni_usb_bulk_register_write(&out_data[i], reg); - while (i % 4) // pad with zeros to 4-byte boundary - out_data[i++] = 0x0; - i += ni_usb_bulk_termination(&out_data[i]); - - mutex_lock(&ni_priv->addressed_transfer_lock); - - retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &usb_bytes_written, 1000); - kfree(out_data); - if (retval || usb_bytes_written != i) { - if (retval == 0) - retval = -EIO; - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, usb_bytes_written=%i, i=%i\n", - retval, usb_bytes_written, i); - mutex_unlock(&ni_priv->addressed_transfer_lock); - return retval; - } - - in_data_length = (length / 30 + 1) * 0x20 + 0x20; - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - return -ENOMEM; - } - retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &usb_bytes_read, - ni_usb_timeout_msecs(board->usec_timeout), 1); - - mutex_unlock(&ni_priv->addressed_transfer_lock); - - if (retval == -ERESTARTSYS) { - } else if (retval) { - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, usb_bytes_read=%i\n", - retval, usb_bytes_read); - kfree(in_data); - return retval; - } - parse_retval = parse_board_ibrd_readback(in_data, &status, buffer, length, &actual_length); - if (parse_retval != usb_bytes_read) { - if (parse_retval >= 0) - parse_retval = -EIO; - dev_err(&usb_dev->dev, "retval=%i usb_bytes_read=%i\n", - parse_retval, usb_bytes_read); - kfree(in_data); - return parse_retval; - } - if (actual_length != length - status.count) { - dev_err(&usb_dev->dev, "actual_length=%i expected=%li\n", - actual_length, (long)(length - status.count)); - ni_usb_dump_raw_block(in_data, usb_bytes_read); - } - kfree(in_data); - switch (status.error_code) { - case NIUSB_NO_ERROR: - retval = 0; - break; - case NIUSB_ABORTED_ERROR: - /* - * this is expected if ni_usb_receive_bulk_msg got - * interrupted by a signal and returned -ERESTARTSYS - */ - break; - case NIUSB_ATN_STATE_ERROR: - if (status.ibsta & DCAS) { - retval = -EINTR; - } else { - retval = -EIO; - dev_dbg(&usb_dev->dev, "read when ATN set stat: 0x%06x\n", status.ibsta); - } - break; - case NIUSB_ADDRESSING_ERROR: - retval = -EIO; - break; - case NIUSB_TIMEOUT_ERROR: - retval = -ETIMEDOUT; - break; - case NIUSB_EOSMODE_ERROR: - dev_err(&usb_dev->dev, "driver bug, we should have been able to avoid NIUSB_EOSMODE_ERROR.\n"); - retval = -EINVAL; - break; - default: - dev_err(&usb_dev->dev, "unknown error code=%i\n", status.error_code); - retval = -EIO; - break; - } - ni_usb_soft_update_status(board, status.ibsta, 0); - if (status.ibsta & END) - *end = 1; - else - *end = 0; - *bytes_read = actual_length; - return retval; -} - -static int ni_usb_write(struct gpib_board *board, u8 *buffer, size_t length, - int send_eoi, size_t *bytes_written) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - u8 *out_data, *in_data; - int out_data_length; - static const int in_data_length = 0x10; - int usb_bytes_written = 0, usb_bytes_read = 0; - int i = 0, j; - int complement_count; - struct ni_usb_status_block status; - static const int max_write_length = 0xffff; - - if (!ni_priv->bus_interface) - return -ENODEV; - if (length > max_write_length) - return -EINVAL; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - out_data_length = length + 0x10; - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return -ENOMEM; - out_data[i++] = 0x0d; - complement_count = length - 1; - complement_count = ~complement_count; - out_data[i++] = complement_count & 0xff; - out_data[i++] = (complement_count >> 8) & 0xff; - out_data[i++] = ni_usb_timeout_code(board->usec_timeout); - out_data[i++] = 0x0; - out_data[i++] = 0x0; - if (send_eoi) - out_data[i++] = 0x8; - else - out_data[i++] = 0x0; - out_data[i++] = 0x0; - for (j = 0; j < length; j++) - out_data[i++] = buffer[j]; - while (i % 4) // pad with zeros to 4-byte boundary - out_data[i++] = 0x0; - i += ni_usb_bulk_termination(&out_data[i]); - - mutex_lock(&ni_priv->addressed_transfer_lock); - - retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &usb_bytes_written, - ni_usb_timeout_msecs(board->usec_timeout)); - kfree(out_data); - if (retval || usb_bytes_written != i) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, usb_bytes_written=%i, i=%i\n", - retval, usb_bytes_written, i); - return retval; - } - - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - return -ENOMEM; - } - retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &usb_bytes_read, - ni_usb_timeout_msecs(board->usec_timeout), 1); - - mutex_unlock(&ni_priv->addressed_transfer_lock); - - if ((retval && retval != -ERESTARTSYS) || usb_bytes_read != 12) { - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, usb_bytes_read=%i\n", - retval, usb_bytes_read); - kfree(in_data); - return retval; - } - ni_usb_parse_status_block(in_data, &status); - kfree(in_data); - switch (status.error_code) { - case NIUSB_NO_ERROR: - retval = 0; - break; - case NIUSB_ABORTED_ERROR: - /* - * this is expected if ni_usb_receive_bulk_msg got - * interrupted by a signal and returned -ERESTARTSYS - */ - break; - case NIUSB_ADDRESSING_ERROR: - dev_err(&usb_dev->dev, "Addressing error retval %d error code=%i\n", - retval, status.error_code); - retval = -ENXIO; - break; - case NIUSB_NO_LISTENER_ERROR: - retval = -ECOMM; - break; - case NIUSB_TIMEOUT_ERROR: - retval = -ETIMEDOUT; - break; - default: - dev_err(&usb_dev->dev, "unknown error code=%i\n", status.error_code); - retval = -EPIPE; - break; - } - ni_usb_soft_update_status(board, status.ibsta, 0); - *bytes_written = length - status.count; - return retval; -} - -static int ni_usb_command_chunk(struct gpib_board *board, u8 *buffer, size_t length, - size_t *command_bytes_written) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - u8 *out_data, *in_data; - int out_data_length; - static const int in_data_length = 0x10; - int bytes_written = 0, bytes_read = 0; - int i = 0, j; - unsigned int complement_count; - struct ni_usb_status_block status; - // usb-b gives error 4 if you try to send more than 16 command bytes at once - static const int max_command_length = 0x10; - - *command_bytes_written = 0; - if (!ni_priv->bus_interface) - return -ENODEV; - if (length > max_command_length) - length = max_command_length; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - out_data_length = length + 0x10; - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return -ENOMEM; - out_data[i++] = 0x0c; - complement_count = length - 1; - complement_count = ~complement_count; - out_data[i++] = complement_count; - out_data[i++] = 0x0; - out_data[i++] = ni_usb_timeout_code(board->usec_timeout); - for (j = 0; j < length; j++) - out_data[i++] = buffer[j]; - while (i % 4) // pad with zeros to 4-byte boundary - out_data[i++] = 0x0; - i += ni_usb_bulk_termination(&out_data[i]); - - mutex_lock(&ni_priv->addressed_transfer_lock); - - retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, - ni_usb_timeout_msecs(board->usec_timeout)); - kfree(out_data); - if (retval || bytes_written != i) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - retval, bytes_written, i); - return retval; - } - - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - return -ENOMEM; - } - - retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, - ni_usb_timeout_msecs(board->usec_timeout), 1); - - mutex_unlock(&ni_priv->addressed_transfer_lock); - - if ((retval && retval != -ERESTARTSYS) || bytes_read != 12) { - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", - retval, bytes_read); - kfree(in_data); - return retval; - } - ni_usb_parse_status_block(in_data, &status); - kfree(in_data); - *command_bytes_written = length - status.count; - switch (status.error_code) { - case NIUSB_NO_ERROR: - break; - case NIUSB_ABORTED_ERROR: - /* - * this is expected if ni_usb_receive_bulk_msg got - * interrupted by a signal and returned -ERESTARTSYS - */ - break; - case NIUSB_NO_BUS_ERROR: - return -ENOTCONN; - case NIUSB_EOSMODE_ERROR: - dev_err(&usb_dev->dev, "got eosmode error. Driver bug?\n"); - return -EIO; - case NIUSB_TIMEOUT_ERROR: - return -ETIMEDOUT; - default: - dev_err(&usb_dev->dev, "unknown error code=%i\n", status.error_code); - return -EIO; - } - ni_usb_soft_update_status(board, status.ibsta, 0); - return 0; -} - -static int ni_usb_command(struct gpib_board *board, u8 *buffer, size_t length, - size_t *bytes_written) -{ - size_t count; - int retval; - - *bytes_written = 0; - while (*bytes_written < length) { - retval = ni_usb_command_chunk(board, buffer + *bytes_written, - length - *bytes_written, &count); - *bytes_written += count; - if (retval < 0) - return retval; - } - return 0; -} - -static int ni_usb_take_control(struct gpib_board *board, int synchronous) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - u8 *out_data, *in_data; - static const int out_data_length = 0x10; - static const int in_data_length = 0x10; - int bytes_written = 0, bytes_read = 0; - int i = 0; - struct ni_usb_status_block status; - - if (!ni_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return -ENOMEM; - out_data[i++] = NIUSB_IBCAC_ID; - if (synchronous) - out_data[i++] = 0x1; - else - out_data[i++] = 0x0; - out_data[i++] = 0x0; - out_data[i++] = 0x0; - i += ni_usb_bulk_termination(&out_data[i]); - - mutex_lock(&ni_priv->addressed_transfer_lock); - - retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); - kfree(out_data); - if (retval || bytes_written != i) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - retval, bytes_written, i); - return retval; - } - - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - return -ENOMEM; - } - retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 1); - - mutex_unlock(&ni_priv->addressed_transfer_lock); - - if ((retval && retval != -ERESTARTSYS) || bytes_read != 12) { - if (retval == 0) - retval = -EIO; - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", - retval, bytes_read); - kfree(in_data); - return retval; - } - ni_usb_parse_status_block(in_data, &status); - kfree(in_data); - ni_usb_soft_update_status(board, status.ibsta, 0); - return retval; -} - -static int ni_usb_go_to_standby(struct gpib_board *board) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - u8 *out_data, *in_data; - static const int out_data_length = 0x10; - static const int in_data_length = 0x20; - int bytes_written = 0, bytes_read = 0; - int i = 0; - struct ni_usb_status_block status; - - if (!ni_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return -ENOMEM; - - out_data[i++] = NIUSB_IBGTS_ID; - out_data[i++] = 0x0; - out_data[i++] = 0x0; - out_data[i++] = 0x0; - i += ni_usb_bulk_termination(&out_data[i]); - - mutex_lock(&ni_priv->addressed_transfer_lock); - - retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); - kfree(out_data); - if (retval || bytes_written != i) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - retval, bytes_written, i); - return retval; - } - - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - return -ENOMEM; - } - retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0); - - mutex_unlock(&ni_priv->addressed_transfer_lock); - - if (retval || bytes_read != 12) { - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", - retval, bytes_read); - kfree(in_data); - return retval; - } - ni_usb_parse_status_block(in_data, &status); - kfree(in_data); - if (status.id != NIUSB_IBGTS_ID) - dev_err(&usb_dev->dev, "bug: status.id 0x%x != INUSB_IBGTS_ID\n", status.id); - ni_usb_soft_update_status(board, status.ibsta, 0); - return 0; -} - -static int ni_usb_request_system_control(struct gpib_board *board, int request_control) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - int i = 0; - struct ni_usb_register writes[4]; - unsigned int ibsta; - - if (!ni_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - if (request_control) { - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = CMDR; - writes[i].value = SETSC; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = AUX_CIFC; - i++; - } else { - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = AUX_CREN; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = AUX_CIFC; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = AUX_DSC; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = CMDR; - writes[i].value = CLRSC; - i++; - } - retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); - if (retval < 0) { - dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); - return retval; - } - if (!request_control) - ni_priv->ren_state = 0; - ni_usb_soft_update_status(board, ibsta, 0); - return 0; -} - -// FIXME maybe the interface should have a "pulse interface clear" function that can return an error? -static void ni_usb_interface_clear(struct gpib_board *board, int assert) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - u8 *out_data, *in_data; - static const int out_data_length = 0x10; - static const int in_data_length = 0x10; - int bytes_written = 0, bytes_read = 0; - int i = 0; - struct ni_usb_status_block status; - - if (!ni_priv->bus_interface) - return; // -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); -// FIXME: we are going to pulse when assert is true, and ignore otherwise - if (assert == 0) - return; - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return; - out_data[i++] = NIUSB_IBSIC_ID; - out_data[i++] = 0x0; - out_data[i++] = 0x0; - out_data[i++] = 0x0; - i += ni_usb_bulk_termination(&out_data[i]); - retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); - kfree(out_data); - if (retval || bytes_written != i) { - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - retval, bytes_written, i); - return; - } - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) - return; - - retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0); - if (retval || bytes_read != 12) { - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", - retval, bytes_read); - kfree(in_data); - return; - } - ni_usb_parse_status_block(in_data, &status); - kfree(in_data); - ni_usb_soft_update_status(board, status.ibsta, 0); -} - -static void ni_usb_remote_enable(struct gpib_board *board, int enable) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - struct ni_usb_register reg; - unsigned int ibsta; - - if (!ni_priv->bus_interface) - return; // -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - reg.device = NIUSB_SUBDEV_TNT4882; - reg.address = nec7210_to_tnt4882_offset(AUXMR); - if (enable) - reg.value = AUX_SREN; - else - reg.value = AUX_CREN; - retval = ni_usb_write_registers(ni_priv, ®, 1, &ibsta); - if (retval < 0) { - dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); - return; //retval; - } - ni_priv->ren_state = enable; - ni_usb_soft_update_status(board, ibsta, 0); - return;// 0; -} - -static int ni_usb_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits) -{ - struct ni_usb_priv *ni_priv = board->private_data; - - ni_priv->eos_char = eos_byte; - ni_priv->eos_mode |= REOS; - if (compare_8_bits) - ni_priv->eos_mode |= BIN; - else - ni_priv->eos_mode &= ~BIN; - return 0; -} - -static void ni_usb_disable_eos(struct gpib_board *board) -{ - struct ni_usb_priv *ni_priv = board->private_data; - /* - * adapter gets unhappy if you don't zero all the bits - * for the eos mode and eos char (returns error 4 on reads). - */ - ni_priv->eos_mode = 0; - ni_priv->eos_char = 0; -} - -static unsigned int ni_usb_update_status(struct gpib_board *board, unsigned int clear_mask) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - static const int buffer_length = 8; - u8 *buffer; - struct ni_usb_status_block status; - - if (!ni_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - buffer = kmalloc(buffer_length, GFP_KERNEL); - if (!buffer) - return board->status; - - retval = ni_usb_receive_control_msg(ni_priv, NI_USB_WAIT_REQUEST, USB_DIR_IN | - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x200, 0x0, buffer, buffer_length, 1000); - if (retval != buffer_length) { - dev_err(&usb_dev->dev, "usb_control_msg returned %i\n", retval); - kfree(buffer); - return board->status; - } - ni_usb_parse_status_block(buffer, &status); - kfree(buffer); - ni_usb_soft_update_status(board, status.ibsta, clear_mask); - return board->status; -} - -// tells ni-usb to immediately stop an ongoing i/o operation -static void ni_usb_stop(struct ni_usb_priv *ni_priv) -{ - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); - int retval; - static const int buffer_length = 8; - u8 *buffer; - struct ni_usb_status_block status; - - buffer = kmalloc(buffer_length, GFP_KERNEL); - if (!buffer) - return; - - retval = ni_usb_receive_control_msg(ni_priv, NI_USB_STOP_REQUEST, USB_DIR_IN | - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0, 0x0, buffer, buffer_length, 1000); - if (retval != buffer_length) { - dev_err(&usb_dev->dev, "usb_control_msg returned %i\n", retval); - kfree(buffer); - return; - } - ni_usb_parse_status_block(buffer, &status); - kfree(buffer); -} - -static int ni_usb_primary_address(struct gpib_board *board, unsigned int address) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - int i = 0; - struct ni_usb_register writes[2]; - unsigned int ibsta; - - if (!ni_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(ADR); - writes[i].value = address; - i++; - writes[i].device = NIUSB_SUBDEV_UNKNOWN2; - writes[i].address = 0x0; - writes[i].value = address; - i++; - retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); - if (retval < 0) { - dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); - return retval; - } - ni_usb_soft_update_status(board, ibsta, 0); - return 0; -} - -static int ni_usb_write_sad(struct ni_usb_register *writes, int address, int enable) -{ - unsigned int adr_bits, admr_bits; - int i = 0; - - adr_bits = HR_ARS; - admr_bits = HR_TRM0 | HR_TRM1; - if (enable) { - adr_bits |= address; - admr_bits |= HR_ADM1; - } else { - adr_bits |= HR_DT | HR_DL; - admr_bits |= HR_ADM0; - } - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(ADR); - writes[i].value = adr_bits; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(ADMR); - writes[i].value = admr_bits; - i++; - writes[i].device = NIUSB_SUBDEV_UNKNOWN2; - writes[i].address = 0x1; - writes[i].value = enable ? MSA(address) : 0x0; - i++; - return i; -} - -static int ni_usb_secondary_address(struct gpib_board *board, unsigned int address, int enable) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - int i = 0; - struct ni_usb_register writes[3]; - unsigned int ibsta; - - if (!ni_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - i += ni_usb_write_sad(writes, address, enable); - retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); - if (retval < 0) { - dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); - return retval; - } - ni_usb_soft_update_status(board, ibsta, 0); - return 0; -} - -static int ni_usb_parallel_poll(struct gpib_board *board, u8 *result) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - u8 *out_data, *in_data; - static const int out_data_length = 0x10; - static const int in_data_length = 0x20; - int bytes_written = 0, bytes_read = 0; - int i = 0; - int j = 0; - struct ni_usb_status_block status; - - if (!ni_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return -ENOMEM; - - out_data[i++] = NIUSB_IBRPP_ID; - out_data[i++] = 0xf0; // FIXME: this should be the parallel poll timeout code - out_data[i++] = 0x0; - out_data[i++] = 0x0; - i += ni_usb_bulk_termination(&out_data[i]); - /*FIXME: 1000 should use parallel poll timeout (not supported yet)*/ - retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); - - kfree(out_data); - if (retval || bytes_written != i) { - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - retval, bytes_written, i); - return retval; - } - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) - return -ENOMEM; - - /*FIXME: should use parallel poll timeout (not supported yet)*/ - retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, - &bytes_read, 1000, 1); - - if (retval && retval != -ERESTARTSYS) { - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", - retval, bytes_read); - kfree(in_data); - return retval; - } - j += ni_usb_parse_status_block(in_data, &status); - *result = in_data[j++]; - kfree(in_data); - ni_usb_soft_update_status(board, status.ibsta, 0); - return retval; -} - -static void ni_usb_parallel_poll_configure(struct gpib_board *board, u8 config) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - int i = 0; - struct ni_usb_register writes[1]; - unsigned int ibsta; - - if (!ni_priv->bus_interface) - return; // -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = PPR | config; - i++; - retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); - if (retval < 0) { - dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); - return;// retval; - } - ni_usb_soft_update_status(board, ibsta, 0); - return;// 0; -} - -static void ni_usb_parallel_poll_response(struct gpib_board *board, int ist) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - int i = 0; - struct ni_usb_register writes[1]; - unsigned int ibsta; - - if (!ni_priv->bus_interface) - return; // -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - if (ist) - writes[i].value = AUX_SPPF; - else - writes[i].value = AUX_CPPF; - i++; - retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); - if (retval < 0) { - dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); - return;// retval; - } - ni_usb_soft_update_status(board, ibsta, 0); - return;// 0; -} - -static void ni_usb_serial_poll_response(struct gpib_board *board, u8 status) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - int i = 0; - struct ni_usb_register writes[1]; - unsigned int ibsta; - - if (!ni_priv->bus_interface) - return; // -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(SPMR); - writes[i].value = status; - i++; - retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); - if (retval < 0) { - dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); - return;// retval; - } - ni_usb_soft_update_status(board, ibsta, 0); - return;// 0; -} - -static u8 ni_usb_serial_poll_status(struct gpib_board *board) -{ - return 0; -} - -static void ni_usb_return_to_local(struct gpib_board *board) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - int i = 0; - struct ni_usb_register writes[1]; - unsigned int ibsta; - - if (!ni_priv->bus_interface) - return; // -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = AUX_RTL; - i++; - retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); - if (retval < 0) { - dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); - return;// retval; - } - ni_usb_soft_update_status(board, ibsta, 0); - return;// 0; -} - -static int ni_usb_line_status(const struct gpib_board *board) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - u8 *out_data, *in_data; - static const int out_data_length = 0x20; - static const int in_data_length = 0x20; - int bytes_written = 0, bytes_read = 0; - int i = 0; - unsigned int bsr_bits; - int line_status = VALID_ALL; - // NI windows driver reads 0xd(HSSEL), 0xc (ARD0), 0x1f (BSR) - - if (!ni_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) - return -ENOMEM; - - /* line status gets called during ibwait */ - retval = mutex_trylock(&ni_priv->addressed_transfer_lock); - - if (retval == 0) { - kfree(out_data); - return -EBUSY; - } - i += ni_usb_bulk_register_read_header(&out_data[i], 1); - i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_TNT4882, BSR); - while (i % 4) - out_data[i++] = 0x0; - i += ni_usb_bulk_termination(&out_data[i]); - retval = ni_usb_nonblocking_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000); - kfree(out_data); - if (retval || bytes_written != i) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - if (retval != -EAGAIN) - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%i\n", - retval, bytes_written, i); - return retval; - } - - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) { - mutex_unlock(&ni_priv->addressed_transfer_lock); - return -ENOMEM; - } - retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, in_data, in_data_length, - &bytes_read, 1000, 0); - - mutex_unlock(&ni_priv->addressed_transfer_lock); - - if (retval) { - if (retval != -EAGAIN) - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", - retval, bytes_read); - kfree(in_data); - return retval; - } - - ni_usb_parse_register_read_block(in_data, &bsr_bits, 1); - kfree(in_data); - if (bsr_bits & BCSR_REN_BIT) - line_status |= BUS_REN; - if (bsr_bits & BCSR_IFC_BIT) - line_status |= BUS_IFC; - if (bsr_bits & BCSR_SRQ_BIT) - line_status |= BUS_SRQ; - if (bsr_bits & BCSR_EOI_BIT) - line_status |= BUS_EOI; - if (bsr_bits & BCSR_NRFD_BIT) - line_status |= BUS_NRFD; - if (bsr_bits & BCSR_NDAC_BIT) - line_status |= BUS_NDAC; - if (bsr_bits & BCSR_DAV_BIT) - line_status |= BUS_DAV; - if (bsr_bits & BCSR_ATN_BIT) - line_status |= BUS_ATN; - return line_status; -} - -static int ni_usb_setup_t1_delay(struct ni_usb_register *reg, unsigned int nano_sec, - unsigned int *actual_ns) -{ - int i = 0; - - *actual_ns = 2000; - - reg[i].device = NIUSB_SUBDEV_TNT4882; - reg[i].address = nec7210_to_tnt4882_offset(AUXMR); - if (nano_sec <= 1100) { - reg[i].value = AUXRI | USTD | SISB; - *actual_ns = 1100; - } else { - reg[i].value = AUXRI | SISB; - } - i++; - reg[i].device = NIUSB_SUBDEV_TNT4882; - reg[i].address = nec7210_to_tnt4882_offset(AUXMR); - if (nano_sec <= 500) { - reg[i].value = AUXRB | HR_TRI; - *actual_ns = 500; - } else { - reg[i].value = AUXRB; - } - i++; - reg[i].device = NIUSB_SUBDEV_TNT4882; - reg[i].address = KEYREG; - if (nano_sec <= 350) { - reg[i].value = MSTD; - *actual_ns = 350; - } else { - reg[i].value = 0x0; - } - i++; - return i; -} - -static int ni_usb_t1_delay(struct gpib_board *board, unsigned int nano_sec) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - struct ni_usb_register writes[3]; - unsigned int ibsta; - unsigned int actual_ns; - int i; - - if (!ni_priv->bus_interface) - return -ENODEV; - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - i = ni_usb_setup_t1_delay(writes, nano_sec, &actual_ns); - retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta); - if (retval < 0) { - dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); - return retval; - } - board->t1_nano_sec = actual_ns; - ni_usb_soft_update_status(board, ibsta, 0); - return actual_ns; -} - -static int ni_usb_allocate_private(struct gpib_board *board) -{ - struct ni_usb_priv *ni_priv; - - board->private_data = kmalloc(sizeof(struct ni_usb_priv), GFP_KERNEL); - if (!board->private_data) - return -ENOMEM; - ni_priv = board->private_data; - memset(ni_priv, 0, sizeof(struct ni_usb_priv)); - mutex_init(&ni_priv->bulk_transfer_lock); - mutex_init(&ni_priv->control_transfer_lock); - mutex_init(&ni_priv->interrupt_transfer_lock); - mutex_init(&ni_priv->addressed_transfer_lock); - return 0; -} - -static void ni_usb_free_private(struct ni_usb_priv *ni_priv) -{ - usb_free_urb(ni_priv->interrupt_urb); - kfree(ni_priv); -} - -#define NUM_INIT_WRITES 26 -static int ni_usb_setup_init(struct gpib_board *board, struct ni_usb_register *writes) -{ - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); - unsigned int mask, actual_ns; - int i = 0; - - writes[i].device = NIUSB_SUBDEV_UNKNOWN3; - writes[i].address = 0x10; - writes[i].value = 0x0; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = CMDR; - writes[i].value = SOFT_RESET; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - mask = AUXRA | HR_HLDA; - if (ni_priv->eos_mode & BIN) - mask |= HR_BIN; - writes[i].value = mask; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = AUXCR; - writes[i].value = mask; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = HSSEL; - writes[i].value = TNT_ONE_CHIP_BIT; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = AUX_CR; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = IMR0; - writes[i].value = TNT_IMR0_ALWAYS_BITS; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(IMR1); - writes[i].value = 0x0; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(IMR2); - writes[i].value = 0x0; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = IMR3; - writes[i].value = 0x0; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = AUX_HLDI; - i++; - - i += ni_usb_setup_t1_delay(&writes[i], board->t1_nano_sec, &actual_ns); - - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = AUXRG | NTNL_BIT; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = CMDR; - if (board->master) - mask = SETSC; // set system controller - else - mask = CLRSC; // clear system controller - writes[i].value = mask; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = AUX_CIFC; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(ADR); - writes[i].value = board->pad; - i++; - writes[i].device = NIUSB_SUBDEV_UNKNOWN2; - writes[i].address = 0x0; - writes[i].value = board->pad; - i++; - - i += ni_usb_write_sad(&writes[i], board->sad, board->sad >= 0); - - writes[i].device = NIUSB_SUBDEV_UNKNOWN2; - writes[i].address = 0x2; // could this be a timeout ? - writes[i].value = 0xfd; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = 0xf; // undocumented address - writes[i].value = 0x11; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = AUX_PON; - i++; - writes[i].device = NIUSB_SUBDEV_TNT4882; - writes[i].address = nec7210_to_tnt4882_offset(AUXMR); - writes[i].value = AUX_CPPF; - i++; - if (i > NUM_INIT_WRITES) { - dev_err(&usb_dev->dev, "bug!, buffer overrun, i=%i\n", i); - return 0; - } - return i; -} - -static int ni_usb_init(struct gpib_board *board) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); - struct ni_usb_register *writes; - unsigned int ibsta; - int writes_len; - - writes = kmalloc_array(NUM_INIT_WRITES, sizeof(*writes), GFP_KERNEL); - if (!writes) - return -ENOMEM; - - writes_len = ni_usb_setup_init(board, writes); - if (writes_len) - retval = ni_usb_write_registers(ni_priv, writes, writes_len, &ibsta); - else - return -EFAULT; - kfree(writes); - if (retval) { - dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); - return retval; - } - ni_usb_soft_update_status(board, ibsta, 0); - return 0; -} - -static void ni_usb_interrupt_complete(struct urb *urb) -{ - struct gpib_board *board = urb->context; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); - int retval; - struct ni_usb_status_block status; - unsigned long flags; - - switch (urb->status) { - /* success */ - case 0: - break; - /* unlinked, don't resubmit */ - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - return; - default: /* other error, resubmit */ - retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_ATOMIC); - if (retval) - dev_err(&usb_dev->dev, "failed to resubmit interrupt urb\n"); - return; - } - - ni_usb_parse_status_block(urb->transfer_buffer, &status); - - spin_lock_irqsave(&board->spinlock, flags); - ni_priv->monitored_ibsta_bits &= ~status.ibsta; - spin_unlock_irqrestore(&board->spinlock, flags); - - wake_up_interruptible(&board->wait); - - retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_ATOMIC); - if (retval) - dev_err(&usb_dev->dev, "failed to resubmit interrupt urb\n"); -} - -static int ni_usb_set_interrupt_monitor(struct gpib_board *board, unsigned int monitored_bits) -{ - int retval; - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); - static const int buffer_length = 8; - u8 *buffer; - struct ni_usb_status_block status; - unsigned long flags; - - buffer = kmalloc(buffer_length, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - spin_lock_irqsave(&board->spinlock, flags); - ni_priv->monitored_ibsta_bits = ni_usb_ibsta_monitor_mask & monitored_bits; - spin_unlock_irqrestore(&board->spinlock, flags); - retval = ni_usb_receive_control_msg(ni_priv, NI_USB_WAIT_REQUEST, USB_DIR_IN | - USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x300, ni_usb_ibsta_monitor_mask & monitored_bits, - buffer, buffer_length, 1000); - if (retval != buffer_length) { - dev_err(&usb_dev->dev, "usb_control_msg returned %i\n", retval); - kfree(buffer); - return -1; - } - ni_usb_parse_status_block(buffer, &status); - kfree(buffer); - return 0; -} - -static int ni_usb_setup_urbs(struct gpib_board *board) -{ - struct ni_usb_priv *ni_priv = board->private_data; - struct usb_device *usb_dev; - int int_pipe; - int retval; - - if (ni_priv->interrupt_in_endpoint < 0) - return 0; - - mutex_lock(&ni_priv->interrupt_transfer_lock); - if (!ni_priv->bus_interface) { - mutex_unlock(&ni_priv->interrupt_transfer_lock); - return -ENODEV; - } - ni_priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!ni_priv->interrupt_urb) { - mutex_unlock(&ni_priv->interrupt_transfer_lock); - return -ENOMEM; - } - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - int_pipe = usb_rcvintpipe(usb_dev, ni_priv->interrupt_in_endpoint); - usb_fill_int_urb(ni_priv->interrupt_urb, usb_dev, int_pipe, ni_priv->interrupt_buffer, - sizeof(ni_priv->interrupt_buffer), &ni_usb_interrupt_complete, board, 1); - retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_KERNEL); - mutex_unlock(&ni_priv->interrupt_transfer_lock); - if (retval) { - dev_err(&usb_dev->dev, "failed to submit first interrupt urb, retval=%i\n", retval); - return retval; - } - return 0; -} - -static void ni_usb_cleanup_urbs(struct ni_usb_priv *ni_priv) -{ - if (ni_priv && ni_priv->bus_interface) { - if (ni_priv->interrupt_urb) - usb_kill_urb(ni_priv->interrupt_urb); - if (ni_priv->bulk_urb) - usb_kill_urb(ni_priv->bulk_urb); - } -} - -static int ni_usb_b_read_serial_number(struct ni_usb_priv *ni_priv) -{ - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); - int retval; - u8 *out_data; - u8 *in_data; - static const int out_data_length = 0x20; - static const int in_data_length = 0x20; - int bytes_written = 0, bytes_read = 0; - int i = 0; - static const int num_reads = 4; - unsigned int results[4]; - int j; - unsigned int serial_number; - - in_data = kmalloc(in_data_length, GFP_KERNEL); - if (!in_data) - return -ENOMEM; - - out_data = kmalloc(out_data_length, GFP_KERNEL); - if (!out_data) { - kfree(in_data); - return -ENOMEM; - } - i += ni_usb_bulk_register_read_header(&out_data[i], num_reads); - i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_1_REG); - i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_2_REG); - i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_3_REG); - i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_4_REG); - while (i % 4) - out_data[i++] = 0x0; - i += ni_usb_bulk_termination(&out_data[i]); - retval = ni_usb_send_bulk_msg(ni_priv, out_data, out_data_length, &bytes_written, 1000); - if (retval) { - dev_err(&usb_dev->dev, "send_bulk_msg returned %i, bytes_written=%i, i=%li\n", - retval, bytes_written, (long)out_data_length); - goto serial_out; - } - retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0); - if (retval) { - dev_err(&usb_dev->dev, "receive_bulk_msg returned %i, bytes_read=%i\n", - retval, bytes_read); - ni_usb_dump_raw_block(in_data, bytes_read); - goto serial_out; - } - if (ARRAY_SIZE(results) < num_reads) { - dev_err(&usb_dev->dev, "serial number eetup bug\n"); - retval = -EINVAL; - goto serial_out; - } - ni_usb_parse_register_read_block(in_data, results, num_reads); - serial_number = 0; - for (j = 0; j < num_reads; ++j) - serial_number |= (results[j] & 0xff) << (8 * j); - dev_dbg(&usb_dev->dev, "board serial number is 0x%x\n", serial_number); - retval = 0; -serial_out: - kfree(in_data); - kfree(out_data); - return retval; -} - -static int ni_usb_hs_wait_for_ready(struct ni_usb_priv *ni_priv) -{ - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); - static const int buffer_size = 0x10; - static const int timeout = 50; - static const int msec_sleep_duration = 100; - int i; int retval; - int j; - int unexpected = 0; - unsigned int serial_number; - u8 *buffer; - - buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - retval = ni_usb_receive_control_msg(ni_priv, NI_USB_SERIAL_NUMBER_REQUEST, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0, 0x0, buffer, buffer_size, 1000); - if (retval < 0) { - dev_err(&usb_dev->dev, "usb_control_msg request 0x%x returned %i\n", - NI_USB_SERIAL_NUMBER_REQUEST, retval); - goto ready_out; - } - j = 0; - if (buffer[j] != NI_USB_SERIAL_NUMBER_REQUEST) { - dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x%x\n", - j, (int)buffer[j], NI_USB_SERIAL_NUMBER_REQUEST); - unexpected = 1; - } - if (unexpected) - ni_usb_dump_raw_block(buffer, retval); - // NI-USB-HS+ pads the serial with 0x0 to make 16 bytes - if (retval != 5 && retval != 16) { - dev_err(&usb_dev->dev, "received unexpected number of bytes = %i, expected 5 or 16\n", - retval); - ni_usb_dump_raw_block(buffer, retval); - } - serial_number = 0; - serial_number |= buffer[++j]; - serial_number |= (buffer[++j] << 8); - serial_number |= (buffer[++j] << 16); - serial_number |= (buffer[++j] << 24); - dev_dbg(&usb_dev->dev, "board serial number is 0x%x\n", serial_number); - for (i = 0; i < timeout; ++i) { - int ready = 0; - - retval = ni_usb_receive_control_msg(ni_priv, NI_USB_POLL_READY_REQUEST, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0, 0x0, buffer, buffer_size, 100); - if (retval < 0) { - dev_err(&usb_dev->dev, "usb_control_msg request 0x%x returned %i\n", - NI_USB_POLL_READY_REQUEST, retval); - goto ready_out; - } - j = 0; - unexpected = 0; - if (buffer[j] != NI_USB_POLL_READY_REQUEST) { // [0] - dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x%x\n", - j, (int)buffer[j], NI_USB_POLL_READY_REQUEST); - unexpected = 1; - } - ++j; - if (buffer[j] != 0x1 && buffer[j] != 0x0) { // [1] HS+ sends 0x0 - dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x1 or 0x0\n", - j, (int)buffer[j]); - unexpected = 1; - } - if (buffer[++j] != 0x0) { // [2] - dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x%x\n", - j, (int)buffer[j], 0x0); - unexpected = 1; - } - ++j; - /* - * MC usb-488 (and sometimes NI-USB-HS?) sends 0x8 here; MC usb-488A sends 0x7 here - * NI-USB-HS+ sends 0x0 - */ - if (buffer[j] != 0x1 && buffer[j] != 0x8 && buffer[j] != 0x7 && buffer[j] != 0x0) { - // [3] - dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x0, 0x1, 0x7 or 0x8\n", - j, (int)buffer[j]); - unexpected = 1; - } - ++j; - // NI-USB-HS+ sends 0 here - if (buffer[j] != 0x30 && buffer[j] != 0x0) { // [4] - dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x0 or 0x30\n", - j, (int)buffer[j]); - unexpected = 1; - } - ++j; - // MC usb-488 (and sometimes NI-USB-HS?) and NI-USB-HS+ sends 0x0 here - if (buffer[j] != 0x1 && buffer[j] != 0x0) { // [5] - dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x1 or 0x0\n", - j, (int)buffer[j]); - unexpected = 1; - } - if (buffer[++j] != 0x0) { // [6] - ready = 1; - // NI-USB-HS+ sends 0xf or 0x19 here - if (buffer[j] != 0x2 && buffer[j] != 0xe && buffer[j] != 0xf && - buffer[j] != 0x16 && buffer[j] != 0x19) { - dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x2, 0xe, 0xf, 0x16 or 0x19\n", - j, (int)buffer[j]); - unexpected = 1; - } - } - if (buffer[++j] != 0x0) { // [7] - ready = 1; - // MC usb-488 sends 0x5 here; MC usb-488A sends 0x6 here - if (buffer[j] != 0x3 && buffer[j] != 0x5 && buffer[j] != 0x6 && - buffer[j] != 0x8) { - dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x3 or 0x5, 0x6 or 0x08\n", - j, (int)buffer[j]); - unexpected = 1; - } - } - ++j; - if (buffer[j] != 0x0 && buffer[j] != 0x2) { // [8] MC usb-488 sends 0x2 here - dev_err(&usb_dev->dev, " unexpected data: buffer[%i]=0x%x, expected 0x0 or 0x2\n", - j, (int)buffer[j]); - unexpected = 1; - } - ++j; - // MC usb-488A and NI-USB-HS sends 0x3 here; NI-USB-HS+ sends 0x30 here - if (buffer[j] != 0x0 && buffer[j] != 0x3 && buffer[j] != 0x30) { // [9] - dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x0, 0x3 or 0x30\n", - j, (int)buffer[j]); - unexpected = 1; - } - if (buffer[++j] != 0x0) { // [10] MC usb-488 sends 0x7 here, new HS+ sends 0x59 - ready = 1; - if (buffer[j] != 0x96 && buffer[j] != 0x7 && buffer[j] != 0x6e && - buffer[j] != 0x59) { - dev_err(&usb_dev->dev, "unexpected data: buffer[%i]=0x%x, expected 0x96, 0x07, 0x6e or 0x59\n", - j, (int)buffer[j]); - unexpected = 1; - } - } - if (unexpected) - ni_usb_dump_raw_block(buffer, retval); - if (ready) - break; - retval = msleep_interruptible(msec_sleep_duration); - if (retval) { - retval = -ERESTARTSYS; - goto ready_out; - } - } - retval = 0; - -ready_out: - kfree(buffer); - dev_dbg(&usb_dev->dev, "exit retval=%d\n", retval); - return retval; -} - -/* - * This does some extra init for HS+ models, as observed on Windows. One of the - * control requests causes the LED to stop blinking. - * I'm not sure what the other 2 requests do. None of these requests are actually required - * for the adapter to work, maybe they do some init for the analyzer interface - * (which we don't use). - */ -static int ni_usb_hs_plus_extra_init(struct ni_usb_priv *ni_priv) -{ - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); - int retval; - u8 *buffer; - static const int buffer_size = 16; - int transfer_size; - - buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - do { - transfer_size = 16; - - retval = ni_usb_receive_control_msg(ni_priv, NI_USB_HS_PLUS_0x48_REQUEST, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0, 0x0, buffer, transfer_size, 1000); - if (retval < 0) { - dev_err(&usb_dev->dev, "usb_control_msg request 0x%x returned %i\n", - NI_USB_HS_PLUS_0x48_REQUEST, retval); - break; - } - // expected response data: 48 f3 30 00 00 00 00 00 00 00 00 00 00 00 00 00 - if (buffer[0] != NI_USB_HS_PLUS_0x48_REQUEST) - dev_err(&usb_dev->dev, "unexpected data: buffer[0]=0x%x, expected 0x%x\n", - (int)buffer[0], NI_USB_HS_PLUS_0x48_REQUEST); - - transfer_size = 2; - - retval = ni_usb_receive_control_msg(ni_priv, NI_USB_HS_PLUS_LED_REQUEST, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x1, 0x0, buffer, transfer_size, 1000); - if (retval < 0) { - dev_err(&usb_dev->dev, "usb_control_msg request 0x%x returned %i\n", - NI_USB_HS_PLUS_LED_REQUEST, retval); - break; - } - // expected response data: 4b 00 - if (buffer[0] != NI_USB_HS_PLUS_LED_REQUEST) - dev_err(&usb_dev->dev, "unexpected data: buffer[0]=0x%x, expected 0x%x\n", - (int)buffer[0], NI_USB_HS_PLUS_LED_REQUEST); - - transfer_size = 9; - - retval = ni_usb_receive_control_msg(ni_priv, NI_USB_HS_PLUS_0xf8_REQUEST, - USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE, - 0x0, 0x1, buffer, transfer_size, 1000); - if (retval < 0) { - dev_err(&usb_dev->dev, "usb_control_msg request 0x%x returned %i\n", - NI_USB_HS_PLUS_0xf8_REQUEST, retval); - break; - } - // expected response data: f8 01 00 00 00 01 00 00 00 - if (buffer[0] != NI_USB_HS_PLUS_0xf8_REQUEST) - dev_err(&usb_dev->dev, "unexpected data: buffer[0]=0x%x, expected 0x%x\n", - (int)buffer[0], NI_USB_HS_PLUS_0xf8_REQUEST); - } while (0); - - // cleanup - kfree(buffer); - return retval; -} - -static inline int ni_usb_device_match(struct usb_interface *interface, - const struct gpib_board_config *config) -{ - if (gpib_match_device_path(&interface->dev, config->device_path) == 0) - return 0; - return 1; -} - -static int ni_usb_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - int retval; - int i, index; - struct ni_usb_priv *ni_priv; - int product_id; - struct usb_device *usb_dev; - - mutex_lock(&ni_usb_hotplug_lock); - retval = ni_usb_allocate_private(board); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - ni_priv = board->private_data; - for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) { - if (ni_usb_driver_interfaces[i] && - !usb_get_intfdata(ni_usb_driver_interfaces[i]) && - ni_usb_device_match(ni_usb_driver_interfaces[i], config)) { - ni_priv->bus_interface = ni_usb_driver_interfaces[i]; - usb_set_intfdata(ni_usb_driver_interfaces[i], board); - usb_dev = interface_to_usbdev(ni_priv->bus_interface); - index = i; - break; - } - } - if (i == MAX_NUM_NI_USB_INTERFACES) { - mutex_unlock(&ni_usb_hotplug_lock); - dev_err(board->gpib_dev, "No supported adapters found, have you loaded its firmware?\n"); - return -ENODEV; - } - if (usb_reset_configuration(interface_to_usbdev(ni_priv->bus_interface))) - dev_err(&usb_dev->dev, "usb_reset_configuration() failed.\n"); - - product_id = le16_to_cpu(usb_dev->descriptor.idProduct); - ni_priv->product_id = product_id; - - timer_setup(&ni_priv->bulk_timer, ni_usb_timeout_handler, 0); - - switch (product_id) { - case USB_DEVICE_ID_NI_USB_B: - ni_priv->bulk_out_endpoint = NIUSB_B_BULK_OUT_ENDPOINT; - ni_priv->bulk_in_endpoint = NIUSB_B_BULK_IN_ENDPOINT; - ni_priv->interrupt_in_endpoint = NIUSB_B_INTERRUPT_IN_ENDPOINT; - ni_usb_b_read_serial_number(ni_priv); - break; - case USB_DEVICE_ID_NI_USB_HS: - case USB_DEVICE_ID_MC_USB_488: - case USB_DEVICE_ID_KUSB_488A: - ni_priv->bulk_out_endpoint = NIUSB_HS_BULK_OUT_ENDPOINT; - ni_priv->bulk_in_endpoint = NIUSB_HS_BULK_IN_ENDPOINT; - ni_priv->interrupt_in_endpoint = NIUSB_HS_INTERRUPT_IN_ENDPOINT; - retval = ni_usb_hs_wait_for_ready(ni_priv); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - break; - case USB_DEVICE_ID_NI_USB_HS_PLUS: - ni_priv->bulk_out_endpoint = NIUSB_HS_PLUS_BULK_OUT_ENDPOINT; - ni_priv->bulk_in_endpoint = NIUSB_HS_PLUS_BULK_IN_ENDPOINT; - ni_priv->interrupt_in_endpoint = NIUSB_HS_PLUS_INTERRUPT_IN_ENDPOINT; - retval = ni_usb_hs_wait_for_ready(ni_priv); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - retval = ni_usb_hs_plus_extra_init(ni_priv); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - break; - default: - mutex_unlock(&ni_usb_hotplug_lock); - dev_err(&usb_dev->dev, "\tDriver bug: unknown endpoints for usb device id %x\n", - product_id); - return -EINVAL; - } - - retval = ni_usb_setup_urbs(board); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - retval = ni_usb_set_interrupt_monitor(board, 0); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - - board->t1_nano_sec = 500; - - retval = ni_usb_init(board); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - retval = ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - - mutex_unlock(&ni_usb_hotplug_lock); - dev_info(&usb_dev->dev, - "bus %d dev num %d attached to gpib%d, intf %i\n", - usb_dev->bus->busnum, usb_dev->devnum, board->minor, index); - return retval; -} - -static int ni_usb_shutdown_hardware(struct ni_usb_priv *ni_priv) -{ - struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface); - int retval; - struct ni_usb_register writes[2]; - static const int writes_length = ARRAY_SIZE(writes); - unsigned int ibsta; - - writes[0].device = NIUSB_SUBDEV_TNT4882; - writes[0].address = nec7210_to_tnt4882_offset(AUXMR); - writes[0].value = AUX_CR; - writes[1].device = NIUSB_SUBDEV_UNKNOWN3; - writes[1].address = 0x10; - writes[1].value = 0x0; - retval = ni_usb_write_registers(ni_priv, writes, writes_length, &ibsta); - if (retval) { - dev_err(&usb_dev->dev, "register write failed, retval=%i\n", retval); - return retval; - } - return 0; -} - -static void ni_usb_detach(struct gpib_board *board) -{ - struct ni_usb_priv *ni_priv; - - mutex_lock(&ni_usb_hotplug_lock); - /* - * under windows, software unplug does chip_reset nec7210 aux command, - * then writes 0x0 to address 0x10 of device 3 - */ - ni_priv = board->private_data; - if (ni_priv) { - if (ni_priv->bus_interface) { - ni_usb_set_interrupt_monitor(board, 0); - ni_usb_shutdown_hardware(ni_priv); - usb_set_intfdata(ni_priv->bus_interface, NULL); - } - mutex_lock(&ni_priv->bulk_transfer_lock); - mutex_lock(&ni_priv->control_transfer_lock); - mutex_lock(&ni_priv->interrupt_transfer_lock); - ni_usb_cleanup_urbs(ni_priv); - ni_usb_free_private(ni_priv); - } - mutex_unlock(&ni_usb_hotplug_lock); -} - -static struct gpib_interface ni_usb_gpib_interface = { - .name = "ni_usb_b", - .attach = ni_usb_attach, - .detach = ni_usb_detach, - .read = ni_usb_read, - .write = ni_usb_write, - .command = ni_usb_command, - .take_control = ni_usb_take_control, - .go_to_standby = ni_usb_go_to_standby, - .request_system_control = ni_usb_request_system_control, - .interface_clear = ni_usb_interface_clear, - .remote_enable = ni_usb_remote_enable, - .enable_eos = ni_usb_enable_eos, - .disable_eos = ni_usb_disable_eos, - .parallel_poll = ni_usb_parallel_poll, - .parallel_poll_configure = ni_usb_parallel_poll_configure, - .parallel_poll_response = ni_usb_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = ni_usb_line_status, - .update_status = ni_usb_update_status, - .primary_address = ni_usb_primary_address, - .secondary_address = ni_usb_secondary_address, - .serial_poll_response = ni_usb_serial_poll_response, - .serial_poll_status = ni_usb_serial_poll_status, - .t1_delay = ni_usb_t1_delay, - .return_to_local = ni_usb_return_to_local, - .skip_check_for_command_acceptors = 1 -}; - -// Table with the USB-devices: just now only testing IDs -static struct usb_device_id ni_usb_driver_device_table[] = { - {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_NI_USB_B)}, - {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_NI_USB_HS)}, - // gpib-usb-hs+ has a second interface for the analyzer, which we ignore - {USB_DEVICE_INTERFACE_NUMBER(USB_VENDOR_ID_NI, USB_DEVICE_ID_NI_USB_HS_PLUS, 0)}, - {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_KUSB_488A)}, - {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_MC_USB_488)}, - {} /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(usb, ni_usb_driver_device_table); - -static int ni_usb_driver_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *usb_dev = interface_to_usbdev(interface); - int i; - char *path; - static const int path_length = 1024; - - mutex_lock(&ni_usb_hotplug_lock); - usb_get_dev(usb_dev); - for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) { - if (!ni_usb_driver_interfaces[i]) { - ni_usb_driver_interfaces[i] = interface; - usb_set_intfdata(interface, NULL); - break; - } - } - if (i == MAX_NUM_NI_USB_INTERFACES) { - usb_put_dev(usb_dev); - mutex_unlock(&ni_usb_hotplug_lock); - dev_err(&usb_dev->dev, "ni_usb_driver_interfaces[] full\n"); - return -1; - } - path = kmalloc(path_length, GFP_KERNEL); - if (!path) { - usb_put_dev(usb_dev); - mutex_unlock(&ni_usb_hotplug_lock); - return -ENOMEM; - } - usb_make_path(usb_dev, path, path_length); - dev_info(&usb_dev->dev, "probe succeeded for path: %s\n", path); - kfree(path); - mutex_unlock(&ni_usb_hotplug_lock); - return 0; -} - -static void ni_usb_driver_disconnect(struct usb_interface *interface) -{ - struct usb_device *usb_dev = interface_to_usbdev(interface); - int i; - - mutex_lock(&ni_usb_hotplug_lock); - for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) { - if (ni_usb_driver_interfaces[i] == interface) { - struct gpib_board *board = usb_get_intfdata(interface); - - if (board) { - struct ni_usb_priv *ni_priv = board->private_data; - - if (ni_priv) { - mutex_lock(&ni_priv->bulk_transfer_lock); - mutex_lock(&ni_priv->control_transfer_lock); - mutex_lock(&ni_priv->interrupt_transfer_lock); - ni_usb_cleanup_urbs(ni_priv); - ni_priv->bus_interface = NULL; - mutex_unlock(&ni_priv->interrupt_transfer_lock); - mutex_unlock(&ni_priv->control_transfer_lock); - mutex_unlock(&ni_priv->bulk_transfer_lock); - } - } - ni_usb_driver_interfaces[i] = NULL; - break; - } - } - if (i == MAX_NUM_NI_USB_INTERFACES) - dev_err(&usb_dev->dev, "unable to find interface bug?\n"); - usb_put_dev(usb_dev); - mutex_unlock(&ni_usb_hotplug_lock); -} - -static int ni_usb_driver_suspend(struct usb_interface *interface, pm_message_t message) -{ - struct usb_device *usb_dev = interface_to_usbdev(interface); - struct gpib_board *board; - int i, retval; - - mutex_lock(&ni_usb_hotplug_lock); - - for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) { - if (ni_usb_driver_interfaces[i] == interface) { - board = usb_get_intfdata(interface); - if (board) - break; - } - } - if (i == MAX_NUM_NI_USB_INTERFACES) { - mutex_unlock(&ni_usb_hotplug_lock); - return 0; - } - - struct ni_usb_priv *ni_priv = board->private_data; - - if (ni_priv) { - ni_usb_set_interrupt_monitor(board, 0); - retval = ni_usb_shutdown_hardware(ni_priv); - if (retval) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - if (ni_priv->interrupt_urb) { - mutex_lock(&ni_priv->interrupt_transfer_lock); - ni_usb_cleanup_urbs(ni_priv); - mutex_unlock(&ni_priv->interrupt_transfer_lock); - } - dev_dbg(&usb_dev->dev, - "bus %d dev num %d gpib%d, interface %i suspended\n", - usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); - } - - mutex_unlock(&ni_usb_hotplug_lock); - return 0; -} - -static int ni_usb_driver_resume(struct usb_interface *interface) -{ - struct usb_device *usb_dev = interface_to_usbdev(interface); - - struct gpib_board *board; - int i, retval; - - mutex_lock(&ni_usb_hotplug_lock); - - for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) { - if (ni_usb_driver_interfaces[i] == interface) { - board = usb_get_intfdata(interface); - if (board) - break; - } - } - if (i == MAX_NUM_NI_USB_INTERFACES) { - mutex_unlock(&ni_usb_hotplug_lock); - return 0; - } - - struct ni_usb_priv *ni_priv = board->private_data; - - if (ni_priv) { - if (ni_priv->interrupt_urb) { - mutex_lock(&ni_priv->interrupt_transfer_lock); - retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_KERNEL); - if (retval) { - dev_err(&usb_dev->dev, "resume failed to resubmit interrupt urb, retval=%i\n", - retval); - mutex_unlock(&ni_priv->interrupt_transfer_lock); - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - mutex_unlock(&ni_priv->interrupt_transfer_lock); - } else { - dev_err(&usb_dev->dev, "bug! resume int urb not set up\n"); - mutex_unlock(&ni_usb_hotplug_lock); - return -EINVAL; - } - - switch (ni_priv->product_id) { - case USB_DEVICE_ID_NI_USB_B: - ni_usb_b_read_serial_number(ni_priv); - break; - case USB_DEVICE_ID_NI_USB_HS: - case USB_DEVICE_ID_MC_USB_488: - case USB_DEVICE_ID_KUSB_488A: - retval = ni_usb_hs_wait_for_ready(ni_priv); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - break; - case USB_DEVICE_ID_NI_USB_HS_PLUS: - retval = ni_usb_hs_wait_for_ready(ni_priv); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - retval = ni_usb_hs_plus_extra_init(ni_priv); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - break; - default: - mutex_unlock(&ni_usb_hotplug_lock); - dev_err(&usb_dev->dev, "\tDriver bug: unknown endpoints for usb device id\n"); - return -EINVAL; - } - - retval = ni_usb_set_interrupt_monitor(board, 0); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - - retval = ni_usb_init(board); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - retval = ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask); - if (retval < 0) { - mutex_unlock(&ni_usb_hotplug_lock); - return retval; - } - if (board->master) - ni_usb_interface_clear(board, 1); // this is a pulsed action - if (ni_priv->ren_state) - ni_usb_remote_enable(board, 1); - - dev_dbg(&usb_dev->dev, - "bus %d dev num %d gpib%d, interface %i resumed\n", - usb_dev->bus->busnum, usb_dev->devnum, board->minor, i); - } - - mutex_unlock(&ni_usb_hotplug_lock); - return 0; -} - -static struct usb_driver ni_usb_bus_driver = { - .name = DRV_NAME, - .probe = ni_usb_driver_probe, - .disconnect = ni_usb_driver_disconnect, - .suspend = ni_usb_driver_suspend, - .resume = ni_usb_driver_resume, - .id_table = ni_usb_driver_device_table, -}; - -static int __init ni_usb_init_module(void) -{ - int i; - int ret; - - for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) - ni_usb_driver_interfaces[i] = NULL; - - ret = usb_register(&ni_usb_bus_driver); - if (ret) { - pr_err("usb_register failed: error = %d\n", ret); - return ret; - } - - ret = gpib_register_driver(&ni_usb_gpib_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - return ret; - } - - return 0; -} - -static void __exit ni_usb_exit_module(void) -{ - gpib_unregister_driver(&ni_usb_gpib_interface); - usb_deregister(&ni_usb_bus_driver); -} - -module_init(ni_usb_init_module); -module_exit(ni_usb_exit_module); diff --git a/drivers/staging/gpib/ni_usb/ni_usb_gpib.h b/drivers/staging/gpib/ni_usb/ni_usb_gpib.h deleted file mode 100644 index 688f5e08792f..000000000000 --- a/drivers/staging/gpib/ni_usb/ni_usb_gpib.h +++ /dev/null @@ -1,226 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2004 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _NI_USB_GPIB_H -#define _NI_USB_GPIB_H - -#include <linux/mutex.h> -#include <linux/semaphore.h> -#include <linux/usb.h> -#include <linux/timer.h> -#include "gpibP.h" - -enum { - USB_VENDOR_ID_NI = 0x3923 -}; - -enum { - USB_DEVICE_ID_NI_USB_B = 0x702a, - USB_DEVICE_ID_NI_USB_B_PREINIT = 0x702b, // device id before firmware is loaded - USB_DEVICE_ID_NI_USB_HS = 0x709b, - USB_DEVICE_ID_NI_USB_HS_PLUS = 0x7618, - USB_DEVICE_ID_KUSB_488A = 0x725c, - USB_DEVICE_ID_MC_USB_488 = 0x725d -}; - -enum ni_usb_device { - NIUSB_SUBDEV_TNT4882 = 1, - NIUSB_SUBDEV_UNKNOWN2 = 2, - NIUSB_SUBDEV_UNKNOWN3 = 3, -}; - -enum endpoint_addresses { - NIUSB_B_BULK_OUT_ENDPOINT = 0x2, - NIUSB_B_BULK_IN_ENDPOINT = 0x2, - NIUSB_B_BULK_IN_ALT_ENDPOINT = 0x6, - NIUSB_B_INTERRUPT_IN_ENDPOINT = 0x4, -}; - -enum hs_enpoint_addresses { - NIUSB_HS_BULK_OUT_ENDPOINT = 0x2, - NIUSB_HS_BULK_OUT_ALT_ENDPOINT = 0x6, - NIUSB_HS_BULK_IN_ENDPOINT = 0x4, - NIUSB_HS_BULK_IN_ALT_ENDPOINT = 0x8, - NIUSB_HS_INTERRUPT_IN_ENDPOINT = 0x1, -}; - -enum hs_plus_endpoint_addresses { - NIUSB_HS_PLUS_BULK_OUT_ENDPOINT = 0x1, - NIUSB_HS_PLUS_BULK_OUT_ALT_ENDPOINT = 0x4, - NIUSB_HS_PLUS_BULK_IN_ENDPOINT = 0x2, - NIUSB_HS_PLUS_BULK_IN_ALT_ENDPOINT = 0x5, - NIUSB_HS_PLUS_INTERRUPT_IN_ENDPOINT = 0x3, -}; - -struct ni_usb_urb_ctx { - struct completion complete; - unsigned timed_out : 1; -}; - -// struct which defines private_data for ni_usb devices -struct ni_usb_priv { - struct usb_interface *bus_interface; - int bulk_out_endpoint; - int bulk_in_endpoint; - int interrupt_in_endpoint; - u8 eos_char; - unsigned short eos_mode; - unsigned int monitored_ibsta_bits; - struct urb *bulk_urb; - struct urb *interrupt_urb; - u8 interrupt_buffer[0x11]; - struct mutex addressed_transfer_lock; // protect transfer lock - struct mutex bulk_transfer_lock; // protect bulk message sends - struct mutex control_transfer_lock; // protect control messages - struct mutex interrupt_transfer_lock; // protect interrupt messages - struct timer_list bulk_timer; - struct ni_usb_urb_ctx context; - int product_id; - unsigned short ren_state; -}; - -struct ni_usb_status_block { - short id; - unsigned short ibsta; - short error_code; - unsigned short count; -}; - -struct ni_usb_register { - enum ni_usb_device device; - short address; - unsigned short value; -}; - -enum ni_usb_bulk_ids { - NIUSB_IBCAC_ID = 0x1, - NIUSB_UNKNOWN3_ID = 0x3, // device level function id? - NIUSB_TERM_ID = 0x4, - NIUSB_IBGTS_ID = 0x6, - NIUSB_IBRPP_ID = 0x7, - NIUSB_REG_READ_ID = 0x8, - NIUSB_REG_WRITE_ID = 0x9, - NIUSB_IBSIC_ID = 0xf, - NIUSB_REGISTER_READ_DATA_START_ID = 0x34, - NIUSB_REGISTER_READ_DATA_END_ID = 0x35, - NIUSB_IBRD_DATA_ID = 0x36, - NIUSB_IBRD_EXTENDED_DATA_ID = 0x37, - NIUSB_IBRD_STATUS_ID = 0x38 -}; - -enum ni_usb_error_codes { - NIUSB_NO_ERROR = 0, - /* - * NIUSB_ABORTED_ERROR occurs when I/O is interrupted early by - * doing a NI_USB_STOP_REQUEST on the control endpoint. - */ - NIUSB_ABORTED_ERROR = 1, - /* - * NIUSB_READ_ATN_ERROR occurs when you do a board read while - * ATN is set - */ - NIUSB_ATN_STATE_ERROR = 2, - /* - * NIUSB_ADDRESSING_ERROR occurs when you do a board - * read/write as CIC but are not in LACS/TACS - */ - NIUSB_ADDRESSING_ERROR = 3, - /* - * NIUSB_EOSMODE_ERROR occurs on reads if any eos mode or char - * bits are set when REOS is not set. - * Have also seen error 4 if you try to send more than 16 - * command bytes at once on a usb-b. - */ - NIUSB_EOSMODE_ERROR = 4, - /* - * NIUSB_NO_BUS_ERROR occurs when you try to write a command - * byte but there are no devices connected to the gpib bus - */ - NIUSB_NO_BUS_ERROR = 5, - /* - * NIUSB_NO_LISTENER_ERROR occurs when you do a board write as - * CIC with no listener - */ - NIUSB_NO_LISTENER_ERROR = 8, - /* get NIUSB_TIMEOUT_ERROR on board read/write timeout */ - NIUSB_TIMEOUT_ERROR = 10, -}; - -enum ni_usb_control_requests { - NI_USB_STOP_REQUEST = 0x20, - NI_USB_WAIT_REQUEST = 0x21, - NI_USB_POLL_READY_REQUEST = 0x40, - NI_USB_SERIAL_NUMBER_REQUEST = 0x41, - NI_USB_HS_PLUS_0x48_REQUEST = 0x48, - NI_USB_HS_PLUS_LED_REQUEST = 0x4b, - NI_USB_HS_PLUS_0xf8_REQUEST = 0xf8 -}; - -static const unsigned int ni_usb_ibsta_monitor_mask = - SRQI | LOK | REM | CIC | ATN | TACS | LACS | DTAS | DCAS; - -static inline int nec7210_to_tnt4882_offset(int offset) -{ - return 2 * offset; -}; - -static inline int ni_usb_bulk_termination(u8 *buffer) -{ - int i = 0; - - buffer[i++] = NIUSB_TERM_ID; - buffer[i++] = 0x0; - buffer[i++] = 0x0; - buffer[i++] = 0x0; - return i; -} - -enum ni_usb_unknown3_register { - SERIAL_NUMBER_4_REG = 0x8, - SERIAL_NUMBER_3_REG = 0x9, - SERIAL_NUMBER_2_REG = 0xa, - SERIAL_NUMBER_1_REG = 0xb, -}; - -static inline int ni_usb_bulk_register_write_header(u8 *buffer, int num_writes) -{ - int i = 0; - - buffer[i++] = NIUSB_REG_WRITE_ID; - buffer[i++] = num_writes; - buffer[i++] = 0x0; - return i; -} - -static inline int ni_usb_bulk_register_write(u8 *buffer, struct ni_usb_register reg) -{ - int i = 0; - - buffer[i++] = reg.device; - buffer[i++] = reg.address; - buffer[i++] = reg.value; - return i; -} - -static inline int ni_usb_bulk_register_read_header(u8 *buffer, int num_reads) -{ - int i = 0; - - buffer[i++] = NIUSB_REG_READ_ID; - buffer[i++] = num_reads; - return i; -} - -static inline int ni_usb_bulk_register_read(u8 *buffer, int device, int address) -{ - int i = 0; - - buffer[i++] = device; - buffer[i++] = address; - return i; -} - -#endif // _NI_USB_GPIB_H diff --git a/drivers/staging/gpib/pc2/Makefile b/drivers/staging/gpib/pc2/Makefile deleted file mode 100644 index 481ee4296e1b..000000000000 --- a/drivers/staging/gpib/pc2/Makefile +++ /dev/null @@ -1,5 +0,0 @@ - -obj-$(CONFIG_GPIB_PC2) += pc2_gpib.o - - - diff --git a/drivers/staging/gpib/pc2/pc2_gpib.c b/drivers/staging/gpib/pc2/pc2_gpib.c deleted file mode 100644 index 9f3943d1df66..000000000000 --- a/drivers/staging/gpib/pc2/pc2_gpib.c +++ /dev/null @@ -1,684 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * copyright : (C) 2001, 2002 by Frank Mori Hess - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt - -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/bitops.h> -#include <asm/dma.h> -#include <linux/dma-mapping.h> -#include <linux/string.h> -#include <linux/init.h> -#include "nec7210.h" -#include "gpibP.h" - -// struct which defines private_data for pc2 driver -struct pc2_priv { - struct nec7210_priv nec7210_priv; - unsigned int irq; - // io address that clears interrupt for pc2a (0x2f0 + irq) - unsigned int clear_intr_addr; -}; - -// pc2 uses 8 consecutive io addresses -static const int pc2_iosize = 8; -static const int pc2a_iosize = 8; -static const int pc2_2a_iosize = 16; - -// offset between io addresses of successive nec7210 registers -static const int pc2a_reg_offset = 0x400; -static const int pc2_reg_offset = 1; - -// interrupt service routine -static irqreturn_t pc2_interrupt(int irq, void *arg); -static irqreturn_t pc2a_interrupt(int irq, void *arg); - -// pc2 specific registers and bits - -// interrupt clear register address -static const int pc2a_clear_intr_iobase = 0x2f0; -static inline unsigned int CLEAR_INTR_REG(unsigned int irq) -{ - return pc2a_clear_intr_iobase + irq; -} - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB driver for PC2/PC2a and compatible devices"); - -/* - * GPIB interrupt service routines - */ - -irqreturn_t pc2_interrupt(int irq, void *arg) -{ - struct gpib_board *board = arg; - struct pc2_priv *priv = board->private_data; - unsigned long flags; - irqreturn_t retval; - - spin_lock_irqsave(&board->spinlock, flags); - retval = nec7210_interrupt(board, &priv->nec7210_priv); - spin_unlock_irqrestore(&board->spinlock, flags); - return retval; -} - -irqreturn_t pc2a_interrupt(int irq, void *arg) -{ - struct gpib_board *board = arg; - struct pc2_priv *priv = board->private_data; - int status1, status2; - unsigned long flags; - irqreturn_t retval; - - spin_lock_irqsave(&board->spinlock, flags); - // read interrupt status (also clears status) - status1 = read_byte(&priv->nec7210_priv, ISR1); - status2 = read_byte(&priv->nec7210_priv, ISR2); - /* clear interrupt circuit */ - if (priv->irq) - outb(0xff, CLEAR_INTR_REG(priv->irq)); - retval = nec7210_interrupt_have_status(board, &priv->nec7210_priv, status1, status2); - spin_unlock_irqrestore(&board->spinlock, flags); - return retval; -} - -// wrappers for interface functions -static int pc2_read(struct gpib_board *board, u8 *buffer, size_t length, int *end, - size_t *bytes_read) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); -} - -static int pc2_write(struct gpib_board *board, u8 *buffer, size_t length, int send_eoi, - size_t *bytes_written) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); -} - -static int pc2_command(struct gpib_board *board, u8 *buffer, - size_t length, size_t *bytes_written) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); -} - -static int pc2_take_control(struct gpib_board *board, int synchronous) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_take_control(board, &priv->nec7210_priv, synchronous); -} - -static int pc2_go_to_standby(struct gpib_board *board) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_go_to_standby(board, &priv->nec7210_priv); -} - -static int pc2_request_system_control(struct gpib_board *board, int request_control) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_request_system_control(board, &priv->nec7210_priv, request_control); -} - -static void pc2_interface_clear(struct gpib_board *board, int assert) -{ - struct pc2_priv *priv = board->private_data; - - nec7210_interface_clear(board, &priv->nec7210_priv, assert); -} - -static void pc2_remote_enable(struct gpib_board *board, int enable) -{ - struct pc2_priv *priv = board->private_data; - - nec7210_remote_enable(board, &priv->nec7210_priv, enable); -} - -static int pc2_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); -} - -static void pc2_disable_eos(struct gpib_board *board) -{ - struct pc2_priv *priv = board->private_data; - - nec7210_disable_eos(board, &priv->nec7210_priv); -} - -static unsigned int pc2_update_status(struct gpib_board *board, unsigned int clear_mask) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_update_status(board, &priv->nec7210_priv, clear_mask); -} - -static int pc2_primary_address(struct gpib_board *board, unsigned int address) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_primary_address(board, &priv->nec7210_priv, address); -} - -static int pc2_secondary_address(struct gpib_board *board, unsigned int address, int enable) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); -} - -static int pc2_parallel_poll(struct gpib_board *board, u8 *result) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_parallel_poll(board, &priv->nec7210_priv, result); -} - -static void pc2_parallel_poll_configure(struct gpib_board *board, u8 config) -{ - struct pc2_priv *priv = board->private_data; - - nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config); -} - -static void pc2_parallel_poll_response(struct gpib_board *board, int ist) -{ - struct pc2_priv *priv = board->private_data; - - nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); -} - -static void pc2_serial_poll_response(struct gpib_board *board, u8 status) -{ - struct pc2_priv *priv = board->private_data; - - nec7210_serial_poll_response(board, &priv->nec7210_priv, status); -} - -static u8 pc2_serial_poll_status(struct gpib_board *board) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_serial_poll_status(board, &priv->nec7210_priv); -} - -static int pc2_t1_delay(struct gpib_board *board, unsigned int nano_sec) -{ - struct pc2_priv *priv = board->private_data; - - return nec7210_t1_delay(board, &priv->nec7210_priv, nano_sec); -} - -static void pc2_return_to_local(struct gpib_board *board) -{ - struct pc2_priv *priv = board->private_data; - - nec7210_return_to_local(board, &priv->nec7210_priv); -} - -static int allocate_private(struct gpib_board *board) -{ - struct pc2_priv *priv; - - board->private_data = kmalloc(sizeof(struct pc2_priv), GFP_KERNEL); - if (!board->private_data) - return -1; - priv = board->private_data; - memset(priv, 0, sizeof(struct pc2_priv)); - init_nec7210_private(&priv->nec7210_priv); - return 0; -} - -static void free_private(struct gpib_board *board) -{ - kfree(board->private_data); - board->private_data = NULL; -} - -static int pc2_generic_attach(struct gpib_board *board, const struct gpib_board_config *config, - enum nec7210_chipset chipset) -{ - struct pc2_priv *pc2_priv; - struct nec7210_priv *nec_priv; - - board->status = 0; - if (allocate_private(board)) - return -ENOMEM; - pc2_priv = board->private_data; - nec_priv = &pc2_priv->nec7210_priv; - nec_priv->read_byte = nec7210_ioport_read_byte; - nec_priv->write_byte = nec7210_ioport_write_byte; - nec_priv->type = chipset; - -#ifndef PC2_DMA - /* - * board->dev hasn't been initialized, so forget about DMA until this driver - * is adapted to use isa_register_driver. - */ - if (config->ibdma) - // driver needs to be adapted to use isa_register_driver to get a struct device* - dev_err(board->gpib_dev, "DMA disabled for pc2 gpib"); -#else - if (config->ibdma) { - nec_priv->dma_buffer_length = 0x1000; - nec_priv->dma_buffer = dma_alloc_coherent(board->dev, - nec_priv->dma_buffer_length, & - nec_priv->dma_buffer_addr, GFP_ATOMIC); - if (!nec_priv->dma_buffer) - return -ENOMEM; - - // request isa dma channel - if (request_dma(config->ibdma, "pc2")) { - dev_err(board->gpib_dev, "can't request DMA %d\n", config->ibdma); - return -1; - } - nec_priv->dma_channel = config->ibdma; - } -#endif - - return 0; -} - -static int pc2_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - int isr_flags = 0; - struct pc2_priv *pc2_priv; - struct nec7210_priv *nec_priv; - int retval; - - retval = pc2_generic_attach(board, config, NEC7210); - if (retval) - return retval; - - pc2_priv = board->private_data; - nec_priv = &pc2_priv->nec7210_priv; - nec_priv->offset = pc2_reg_offset; - - if (!request_region(config->ibbase, pc2_iosize, "pc2")) { - dev_err(board->gpib_dev, "ioports are already in use\n"); - return -EBUSY; - } - nec_priv->iobase = config->ibbase; - - nec7210_board_reset(nec_priv, board); - - // install interrupt handler - if (config->ibirq) { - if (request_irq(config->ibirq, pc2_interrupt, isr_flags, "pc2", board)) { - dev_err(board->gpib_dev, "can't request IRQ %d\n", config->ibirq); - return -EBUSY; - } - } - pc2_priv->irq = config->ibirq; - /* poll so we can detect assertion of ATN */ - if (gpib_request_pseudo_irq(board, pc2_interrupt)) { - dev_err(board->gpib_dev, "failed to allocate pseudo_irq\n"); - return -1; - } - /* set internal counter register for 8 MHz input clock */ - write_byte(nec_priv, ICR | 8, AUXMR); - - nec7210_board_online(nec_priv, board); - - return 0; -} - -static void pc2_detach(struct gpib_board *board) -{ - struct pc2_priv *pc2_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (pc2_priv) { - nec_priv = &pc2_priv->nec7210_priv; -#ifdef PC2_DMA - if (nec_priv->dma_channel) - free_dma(nec_priv->dma_channel); -#endif - gpib_free_pseudo_irq(board); - if (pc2_priv->irq) - free_irq(pc2_priv->irq, board); - if (nec_priv->iobase) { - nec7210_board_reset(nec_priv, board); - release_region(nec_priv->iobase, pc2_iosize); - } - if (nec_priv->dma_buffer) { - dma_free_coherent(board->dev, nec_priv->dma_buffer_length, - nec_priv->dma_buffer, nec_priv->dma_buffer_addr); - nec_priv->dma_buffer = NULL; - } - } - free_private(board); -} - -static int pc2a_common_attach(struct gpib_board *board, const struct gpib_board_config *config, - unsigned int num_registers, enum nec7210_chipset chipset) -{ - unsigned int i, j; - struct pc2_priv *pc2_priv; - struct nec7210_priv *nec_priv; - int retval; - - retval = pc2_generic_attach(board, config, chipset); - if (retval) - return retval; - - pc2_priv = board->private_data; - nec_priv = &pc2_priv->nec7210_priv; - nec_priv->offset = pc2a_reg_offset; - - switch (config->ibbase) { - case 0x02e1: - case 0x22e1: - case 0x42e1: - case 0x62e1: - break; - default: - dev_err(board->gpib_dev, "PCIIa base range invalid, must be one of 0x[0246]2e1, but is 0x%x\n", - config->ibbase); - return -1; - } - - if (config->ibirq) { - if (config->ibirq < 2 || config->ibirq > 7) { - dev_err(board->gpib_dev, "illegal interrupt level %i\n", - config->ibirq); - return -1; - } - } else { - dev_err(board->gpib_dev, "interrupt disabled, using polling mode (slow)\n"); - } -#ifdef CHECK_IOPORTS - unsigned int err = 0; - - for (i = 0; i < num_registers; i++) { - if (check_region(config->ibbase + i * pc2a_reg_offset, 1)) - err++; - } - if (config->ibirq && check_region(pc2a_clear_intr_iobase + config->ibirq, 1)) - err++; - if (err) { - dev_err(board->gpib_dev, "ioports are already in use"); - return -EBUSY; - } -#endif - for (i = 0; i < num_registers; i++) { - if (!request_region(config->ibbase + - i * pc2a_reg_offset, 1, "pc2a")) { - dev_err(board->gpib_dev, "ioports are already in use"); - for (j = 0; j < i; j++) - release_region(config->ibbase + - j * pc2a_reg_offset, 1); - return -EBUSY; - } - } - nec_priv->iobase = config->ibbase; - if (config->ibirq) { - if (!request_region(pc2a_clear_intr_iobase + config->ibirq, 1, "pc2a")) { - dev_err(board->gpib_dev, "ioports are already in use"); - return -1; - } - pc2_priv->clear_intr_addr = pc2a_clear_intr_iobase + config->ibirq; - if (request_irq(config->ibirq, pc2a_interrupt, 0, "pc2a", board)) { - dev_err(board->gpib_dev, "can't request IRQ %d\n", config->ibirq); - return -EBUSY; - } - } - pc2_priv->irq = config->ibirq; - /* poll so we can detect assertion of ATN */ - if (gpib_request_pseudo_irq(board, pc2_interrupt)) { - dev_err(board->gpib_dev, "failed to allocate pseudo_irq\n"); - return -1; - } - - // make sure interrupt is clear - if (pc2_priv->irq) - outb(0xff, CLEAR_INTR_REG(pc2_priv->irq)); - - nec7210_board_reset(nec_priv, board); - - /* set internal counter register for 8 MHz input clock */ - write_byte(nec_priv, ICR | 8, AUXMR); - - nec7210_board_online(nec_priv, board); - - return 0; -} - -static int pc2a_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - return pc2a_common_attach(board, config, pc2a_iosize, NEC7210); -} - -static int pc2a_cb7210_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - return pc2a_common_attach(board, config, pc2a_iosize, CB7210); -} - -static int pc2_2a_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - return pc2a_common_attach(board, config, pc2_2a_iosize, NAT4882); -} - -static void pc2a_common_detach(struct gpib_board *board, unsigned int num_registers) -{ - int i; - struct pc2_priv *pc2_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (pc2_priv) { - nec_priv = &pc2_priv->nec7210_priv; -#ifdef PC2_DMA - if (nec_priv->dma_channel) - free_dma(nec_priv->dma_channel); -#endif - gpib_free_pseudo_irq(board); - if (pc2_priv->irq) - free_irq(pc2_priv->irq, board); - if (nec_priv->iobase) { - nec7210_board_reset(nec_priv, board); - for (i = 0; i < num_registers; i++) - release_region(nec_priv->iobase + - i * pc2a_reg_offset, 1); - } - if (pc2_priv->clear_intr_addr) - release_region(pc2_priv->clear_intr_addr, 1); - if (nec_priv->dma_buffer) { - dma_free_coherent(board->dev, nec_priv->dma_buffer_length, - nec_priv->dma_buffer, - nec_priv->dma_buffer_addr); - nec_priv->dma_buffer = NULL; - } - } - free_private(board); -} - -static void pc2a_detach(struct gpib_board *board) -{ - pc2a_common_detach(board, pc2a_iosize); -} - -static void pc2_2a_detach(struct gpib_board *board) -{ - pc2a_common_detach(board, pc2_2a_iosize); -} - -static struct gpib_interface pc2_interface = { - .name = "pcII", - .attach = pc2_attach, - .detach = pc2_detach, - .read = pc2_read, - .write = pc2_write, - .command = pc2_command, - .take_control = pc2_take_control, - .go_to_standby = pc2_go_to_standby, - .request_system_control = pc2_request_system_control, - .interface_clear = pc2_interface_clear, - .remote_enable = pc2_remote_enable, - .enable_eos = pc2_enable_eos, - .disable_eos = pc2_disable_eos, - .parallel_poll = pc2_parallel_poll, - .parallel_poll_configure = pc2_parallel_poll_configure, - .parallel_poll_response = pc2_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = NULL, - .update_status = pc2_update_status, - .primary_address = pc2_primary_address, - .secondary_address = pc2_secondary_address, - .serial_poll_response = pc2_serial_poll_response, - .serial_poll_status = pc2_serial_poll_status, - .t1_delay = pc2_t1_delay, - .return_to_local = pc2_return_to_local, -}; - -static struct gpib_interface pc2a_interface = { - .name = "pcIIa", - .attach = pc2a_attach, - .detach = pc2a_detach, - .read = pc2_read, - .write = pc2_write, - .command = pc2_command, - .take_control = pc2_take_control, - .go_to_standby = pc2_go_to_standby, - .request_system_control = pc2_request_system_control, - .interface_clear = pc2_interface_clear, - .remote_enable = pc2_remote_enable, - .enable_eos = pc2_enable_eos, - .disable_eos = pc2_disable_eos, - .parallel_poll = pc2_parallel_poll, - .parallel_poll_configure = pc2_parallel_poll_configure, - .parallel_poll_response = pc2_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = NULL, - .update_status = pc2_update_status, - .primary_address = pc2_primary_address, - .secondary_address = pc2_secondary_address, - .serial_poll_response = pc2_serial_poll_response, - .serial_poll_status = pc2_serial_poll_status, - .t1_delay = pc2_t1_delay, - .return_to_local = pc2_return_to_local, -}; - -static struct gpib_interface pc2a_cb7210_interface = { - .name = "pcIIa_cb7210", - .attach = pc2a_cb7210_attach, - .detach = pc2a_detach, - .read = pc2_read, - .write = pc2_write, - .command = pc2_command, - .take_control = pc2_take_control, - .go_to_standby = pc2_go_to_standby, - .request_system_control = pc2_request_system_control, - .interface_clear = pc2_interface_clear, - .remote_enable = pc2_remote_enable, - .enable_eos = pc2_enable_eos, - .disable_eos = pc2_disable_eos, - .parallel_poll = pc2_parallel_poll, - .parallel_poll_configure = pc2_parallel_poll_configure, - .parallel_poll_response = pc2_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = NULL, // XXX - .update_status = pc2_update_status, - .primary_address = pc2_primary_address, - .secondary_address = pc2_secondary_address, - .serial_poll_response = pc2_serial_poll_response, - .serial_poll_status = pc2_serial_poll_status, - .t1_delay = pc2_t1_delay, - .return_to_local = pc2_return_to_local, -}; - -static struct gpib_interface pc2_2a_interface = { - .name = "pcII_IIa", - .attach = pc2_2a_attach, - .detach = pc2_2a_detach, - .read = pc2_read, - .write = pc2_write, - .command = pc2_command, - .take_control = pc2_take_control, - .go_to_standby = pc2_go_to_standby, - .request_system_control = pc2_request_system_control, - .interface_clear = pc2_interface_clear, - .remote_enable = pc2_remote_enable, - .enable_eos = pc2_enable_eos, - .disable_eos = pc2_disable_eos, - .parallel_poll = pc2_parallel_poll, - .parallel_poll_configure = pc2_parallel_poll_configure, - .parallel_poll_response = pc2_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = NULL, - .update_status = pc2_update_status, - .primary_address = pc2_primary_address, - .secondary_address = pc2_secondary_address, - .serial_poll_response = pc2_serial_poll_response, - .serial_poll_status = pc2_serial_poll_status, - .t1_delay = pc2_t1_delay, - .return_to_local = pc2_return_to_local, -}; - -static int __init pc2_init_module(void) -{ - int ret; - - ret = gpib_register_driver(&pc2_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - return ret; - } - - ret = gpib_register_driver(&pc2a_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pc2a; - } - - ret = gpib_register_driver(&pc2a_cb7210_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_cb7210; - } - - ret = gpib_register_driver(&pc2_2a_interface, THIS_MODULE); - if (ret) { - pr_err("gpib_register_driver failed: error = %d\n", ret); - goto err_pc2_2a; - } - - return 0; - -err_pc2_2a: - gpib_unregister_driver(&pc2a_cb7210_interface); -err_cb7210: - gpib_unregister_driver(&pc2a_interface); -err_pc2a: - gpib_unregister_driver(&pc2_interface); - - return ret; -} - -static void __exit pc2_exit_module(void) -{ - gpib_unregister_driver(&pc2_interface); - gpib_unregister_driver(&pc2a_interface); - gpib_unregister_driver(&pc2a_cb7210_interface); - gpib_unregister_driver(&pc2_2a_interface); -} - -module_init(pc2_init_module); -module_exit(pc2_exit_module); - diff --git a/drivers/staging/gpib/tms9914/Makefile b/drivers/staging/gpib/tms9914/Makefile deleted file mode 100644 index 4705ab07f413..000000000000 --- a/drivers/staging/gpib/tms9914/Makefile +++ /dev/null @@ -1,6 +0,0 @@ - -obj-$(CONFIG_GPIB_TMS9914) += tms9914.o - - - - diff --git a/drivers/staging/gpib/tms9914/tms9914.c b/drivers/staging/gpib/tms9914/tms9914.c deleted file mode 100644 index 0d11b80bb982..000000000000 --- a/drivers/staging/gpib/tms9914/tms9914.c +++ /dev/null @@ -1,914 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * copyright : (C) 2001, 2002 by Frank Mori Hess - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt - -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <asm/dma.h> -#include <linux/io.h> -#include <linux/bitops.h> -#include <linux/pci.h> -#include <linux/pci_ids.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/delay.h> - -#include "gpibP.h" -#include "tms9914.h" - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB library for tms9914"); - -static unsigned int update_status_nolock(struct gpib_board *board, struct tms9914_priv *priv); - -int tms9914_take_control(struct gpib_board *board, struct tms9914_priv *priv, int synchronous) -{ - int i; - const int timeout = 100; - - if (synchronous) - write_byte(priv, AUX_TCS, AUXCR); - else - write_byte(priv, AUX_TCA, AUXCR); - // busy wait until ATN is asserted - for (i = 0; i < timeout; i++) { - if ((read_byte(priv, ADSR) & HR_ATN)) - break; - udelay(1); - } - if (i == timeout) - return -ETIMEDOUT; - - clear_bit(WRITE_READY_BN, &priv->state); - - return 0; -} -EXPORT_SYMBOL_GPL(tms9914_take_control); - -/* - * The agilent 82350B has a buggy implementation of tcs which interferes with the - * operation of tca. It appears to be based on the controller state machine - * described in the TI 9900 TMS9914A data manual published in 1982. This - * manual describes tcs as putting the controller into a CWAS - * state where it waits indefinitely for ANRS and ignores tca. Since a - * functioning tca is far more important than tcs, we work around the - * problem by never issuing tcs. - * - * I don't know if this problem exists in the real tms9914a or just in the fpga - * of the 82350B. For now, only the agilent_82350b uses this workaround. - * The rest of the tms9914 based drivers still use tms9914_take_control - * directly (which does issue tcs). - */ -int tms9914_take_control_workaround(struct gpib_board *board, - struct tms9914_priv *priv, int synchronous) -{ - if (synchronous) - return -ETIMEDOUT; - return tms9914_take_control(board, priv, synchronous); -} -EXPORT_SYMBOL_GPL(tms9914_take_control_workaround); - -int tms9914_go_to_standby(struct gpib_board *board, struct tms9914_priv *priv) -{ - int i; - const int timeout = 1000; - - write_byte(priv, AUX_GTS, AUXCR); - // busy wait until ATN is released - for (i = 0; i < timeout; i++) { - if ((read_byte(priv, ADSR) & HR_ATN) == 0) - break; - udelay(1); - } - if (i == timeout) - return -ETIMEDOUT; - - clear_bit(COMMAND_READY_BN, &priv->state); - - return 0; -} -EXPORT_SYMBOL_GPL(tms9914_go_to_standby); - -void tms9914_interface_clear(struct gpib_board *board, struct tms9914_priv *priv, int assert) -{ - if (assert) { - write_byte(priv, AUX_SIC | AUX_CS, AUXCR); - - set_bit(CIC_NUM, &board->status); - } else { - write_byte(priv, AUX_SIC, AUXCR); - } -} -EXPORT_SYMBOL_GPL(tms9914_interface_clear); - -void tms9914_remote_enable(struct gpib_board *board, struct tms9914_priv *priv, int enable) -{ - if (enable) - write_byte(priv, AUX_SRE | AUX_CS, AUXCR); - else - write_byte(priv, AUX_SRE, AUXCR); -} -EXPORT_SYMBOL_GPL(tms9914_remote_enable); - -int tms9914_request_system_control(struct gpib_board *board, struct tms9914_priv *priv, - int request_control) -{ - if (request_control) { - write_byte(priv, AUX_RQC, AUXCR); - } else { - clear_bit(CIC_NUM, &board->status); - write_byte(priv, AUX_RLC, AUXCR); - } - return 0; -} -EXPORT_SYMBOL_GPL(tms9914_request_system_control); - -unsigned int tms9914_t1_delay(struct gpib_board *board, struct tms9914_priv *priv, - unsigned int nano_sec) -{ - static const int clock_period = 200; // assuming 5Mhz input clock - int num_cycles; - - num_cycles = 12; - - if (nano_sec <= 8 * clock_period) { - write_byte(priv, AUX_STDL | AUX_CS, AUXCR); - num_cycles = 8; - } else { - write_byte(priv, AUX_STDL, AUXCR); - } - - if (nano_sec <= 4 * clock_period) { - write_byte(priv, AUX_VSTDL | AUX_CS, AUXCR); - num_cycles = 4; - } else { - write_byte(priv, AUX_VSTDL, AUXCR); - } - - return num_cycles * clock_period; -} -EXPORT_SYMBOL_GPL(tms9914_t1_delay); - -void tms9914_return_to_local(const struct gpib_board *board, struct tms9914_priv *priv) -{ - write_byte(priv, AUX_RTL, AUXCR); -} -EXPORT_SYMBOL_GPL(tms9914_return_to_local); - -void tms9914_set_holdoff_mode(struct tms9914_priv *priv, enum tms9914_holdoff_mode mode) -{ - switch (mode) { - case TMS9914_HOLDOFF_NONE: - write_byte(priv, AUX_HLDE, AUXCR); - write_byte(priv, AUX_HLDA, AUXCR); - break; - case TMS9914_HOLDOFF_EOI: - write_byte(priv, AUX_HLDE | AUX_CS, AUXCR); - write_byte(priv, AUX_HLDA, AUXCR); - break; - case TMS9914_HOLDOFF_ALL: - write_byte(priv, AUX_HLDE, AUXCR); - write_byte(priv, AUX_HLDA | AUX_CS, AUXCR); - break; - default: - pr_err("bug! bad holdoff mode %i\n", mode); - break; - } - priv->holdoff_mode = mode; -} -EXPORT_SYMBOL_GPL(tms9914_set_holdoff_mode); - -void tms9914_release_holdoff(struct tms9914_priv *priv) -{ - if (priv->holdoff_active) { - write_byte(priv, AUX_RHDF, AUXCR); - priv->holdoff_active = 0; - } -} -EXPORT_SYMBOL_GPL(tms9914_release_holdoff); - -int tms9914_enable_eos(struct gpib_board *board, struct tms9914_priv *priv, u8 eos_byte, - int compare_8_bits) -{ - priv->eos = eos_byte; - priv->eos_flags = REOS; - if (compare_8_bits) - priv->eos_flags |= BIN; - return 0; -} -EXPORT_SYMBOL(tms9914_enable_eos); - -void tms9914_disable_eos(struct gpib_board *board, struct tms9914_priv *priv) -{ - priv->eos_flags &= ~REOS; -} -EXPORT_SYMBOL(tms9914_disable_eos); - -int tms9914_parallel_poll(struct gpib_board *board, struct tms9914_priv *priv, u8 *result) -{ - // execute parallel poll - write_byte(priv, AUX_CS | AUX_RPP, AUXCR); - udelay(2); - *result = read_byte(priv, CPTR); - // clear parallel poll state - write_byte(priv, AUX_RPP, AUXCR); - return 0; -} -EXPORT_SYMBOL(tms9914_parallel_poll); - -static void set_ppoll_reg(struct tms9914_priv *priv, int enable, - unsigned int dio_line, int sense, int ist) -{ - u8 dio_byte; - - if (enable && ((sense && ist) || (!sense && !ist))) { - dio_byte = 1 << (dio_line - 1); - write_byte(priv, dio_byte, PPR); - } else { - write_byte(priv, 0, PPR); - } -} - -void tms9914_parallel_poll_configure(struct gpib_board *board, - struct tms9914_priv *priv, u8 config) -{ - priv->ppoll_enable = (config & PPC_DISABLE) == 0; - priv->ppoll_line = (config & PPC_DIO_MASK) + 1; - priv->ppoll_sense = (config & PPC_SENSE) != 0; - set_ppoll_reg(priv, priv->ppoll_enable, priv->ppoll_line, priv->ppoll_sense, board->ist); -} -EXPORT_SYMBOL(tms9914_parallel_poll_configure); - -void tms9914_parallel_poll_response(struct gpib_board *board, - struct tms9914_priv *priv, int ist) -{ - set_ppoll_reg(priv, priv->ppoll_enable, priv->ppoll_line, priv->ppoll_sense, ist); -} -EXPORT_SYMBOL(tms9914_parallel_poll_response); - -void tms9914_serial_poll_response(struct gpib_board *board, - struct tms9914_priv *priv, u8 status) -{ - unsigned long flags; - - spin_lock_irqsave(&board->spinlock, flags); - write_byte(priv, status, SPMR); - priv->spoll_status = status; - if (status & request_service_bit) - write_byte(priv, AUX_RSV2 | AUX_CS, AUXCR); - else - write_byte(priv, AUX_RSV2, AUXCR); - spin_unlock_irqrestore(&board->spinlock, flags); -} -EXPORT_SYMBOL(tms9914_serial_poll_response); - -u8 tms9914_serial_poll_status(struct gpib_board *board, struct tms9914_priv *priv) -{ - u8 status; - unsigned long flags; - - spin_lock_irqsave(&board->spinlock, flags); - status = priv->spoll_status; - spin_unlock_irqrestore(&board->spinlock, flags); - - return status; -} -EXPORT_SYMBOL(tms9914_serial_poll_status); - -int tms9914_primary_address(struct gpib_board *board, - struct tms9914_priv *priv, unsigned int address) -{ - // put primary address in address0 - write_byte(priv, address & ADDRESS_MASK, ADR); - return 0; -} -EXPORT_SYMBOL(tms9914_primary_address); - -int tms9914_secondary_address(struct gpib_board *board, struct tms9914_priv *priv, - unsigned int address, int enable) -{ - if (enable) - priv->imr1_bits |= HR_APTIE; - else - priv->imr1_bits &= ~HR_APTIE; - - write_byte(priv, priv->imr1_bits, IMR1); - return 0; -} -EXPORT_SYMBOL(tms9914_secondary_address); - -unsigned int tms9914_update_status(struct gpib_board *board, struct tms9914_priv *priv, - unsigned int clear_mask) -{ - unsigned long flags; - unsigned int retval; - - spin_lock_irqsave(&board->spinlock, flags); - retval = update_status_nolock(board, priv); - board->status &= ~clear_mask; - spin_unlock_irqrestore(&board->spinlock, flags); - - return retval; -} -EXPORT_SYMBOL(tms9914_update_status); - -static void update_talker_state(struct tms9914_priv *priv, unsigned int address_status_bits) -{ - if (address_status_bits & HR_TA) { - if (address_status_bits & HR_ATN) - priv->talker_state = talker_addressed; - else - /* - * this could also be serial_poll_active, but the tms9914 provides no - * way to distinguish, so we'll assume talker_active - */ - priv->talker_state = talker_active; - } else { - priv->talker_state = talker_idle; - } -} - -static void update_listener_state(struct tms9914_priv *priv, unsigned int address_status_bits) -{ - if (address_status_bits & HR_LA) { - if (address_status_bits & HR_ATN) - priv->listener_state = listener_addressed; - else - priv->listener_state = listener_active; - } else { - priv->listener_state = listener_idle; - } -} - -static unsigned int update_status_nolock(struct gpib_board *board, struct tms9914_priv *priv) -{ - int address_status; - int bsr_bits; - - address_status = read_byte(priv, ADSR); - - // check for remote/local - if (address_status & HR_REM) - set_bit(REM_NUM, &board->status); - else - clear_bit(REM_NUM, &board->status); - // check for lockout - if (address_status & HR_LLO) - set_bit(LOK_NUM, &board->status); - else - clear_bit(LOK_NUM, &board->status); - // check for ATN - if (address_status & HR_ATN) - set_bit(ATN_NUM, &board->status); - else - clear_bit(ATN_NUM, &board->status); - // check for talker/listener addressed - update_talker_state(priv, address_status); - if (priv->talker_state == talker_active || priv->talker_state == talker_addressed) - set_bit(TACS_NUM, &board->status); - else - clear_bit(TACS_NUM, &board->status); - - update_listener_state(priv, address_status); - if (priv->listener_state == listener_active || priv->listener_state == listener_addressed) - set_bit(LACS_NUM, &board->status); - else - clear_bit(LACS_NUM, &board->status); - // Check for SRQI - not reset elsewhere except in autospoll - if (board->status & SRQI) { - bsr_bits = read_byte(priv, BSR); - if (!(bsr_bits & BSR_SRQ_BIT)) - clear_bit(SRQI_NUM, &board->status); - } - - dev_dbg(board->gpib_dev, "status 0x%lx, state 0x%lx\n", board->status, priv->state); - - return board->status; -} - -int tms9914_line_status(const struct gpib_board *board, struct tms9914_priv *priv) -{ - int bsr_bits; - int status = VALID_ALL; - - bsr_bits = read_byte(priv, BSR); - - if (bsr_bits & BSR_REN_BIT) - status |= BUS_REN; - if (bsr_bits & BSR_IFC_BIT) - status |= BUS_IFC; - if (bsr_bits & BSR_SRQ_BIT) - status |= BUS_SRQ; - if (bsr_bits & BSR_EOI_BIT) - status |= BUS_EOI; - if (bsr_bits & BSR_NRFD_BIT) - status |= BUS_NRFD; - if (bsr_bits & BSR_NDAC_BIT) - status |= BUS_NDAC; - if (bsr_bits & BSR_DAV_BIT) - status |= BUS_DAV; - if (bsr_bits & BSR_ATN_BIT) - status |= BUS_ATN; - - return status; -} -EXPORT_SYMBOL(tms9914_line_status); - -static int check_for_eos(struct tms9914_priv *priv, u8 byte) -{ - static const u8 seven_bit_compare_mask = 0x7f; - - if ((priv->eos_flags & REOS) == 0) - return 0; - - if (priv->eos_flags & BIN) { - if (priv->eos == byte) - return 1; - } else { - if ((priv->eos & seven_bit_compare_mask) == (byte & seven_bit_compare_mask)) - return 1; - } - return 0; -} - -static int wait_for_read_byte(struct gpib_board *board, struct tms9914_priv *priv) -{ - if (wait_event_interruptible(board->wait, - test_bit(READ_READY_BN, &priv->state) || - test_bit(DEV_CLEAR_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) - return -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - return -ETIMEDOUT; - - if (test_bit(DEV_CLEAR_BN, &priv->state)) - return -EINTR; - return 0; -} - -static inline u8 tms9914_read_data_in(struct gpib_board *board, - struct tms9914_priv *priv, int *end) -{ - unsigned long flags; - u8 data; - - spin_lock_irqsave(&board->spinlock, flags); - clear_bit(READ_READY_BN, &priv->state); - data = read_byte(priv, DIR); - if (test_and_clear_bit(RECEIVED_END_BN, &priv->state)) - *end = 1; - else - *end = 0; - switch (priv->holdoff_mode) { - case TMS9914_HOLDOFF_EOI: - if (*end) - priv->holdoff_active = 1; - break; - case TMS9914_HOLDOFF_ALL: - priv->holdoff_active = 1; - break; - case TMS9914_HOLDOFF_NONE: - break; - default: - dev_err(board->gpib_dev, "bug! bad holdoff mode %i\n", priv->holdoff_mode); - break; - } - spin_unlock_irqrestore(&board->spinlock, flags); - - return data; -} - -static int pio_read(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, - size_t length, int *end, size_t *bytes_read) -{ - ssize_t retval = 0; - - *bytes_read = 0; - *end = 0; - while (*bytes_read < length && *end == 0) { - tms9914_release_holdoff(priv); - retval = wait_for_read_byte(board, priv); - if (retval < 0) - return retval; - buffer[(*bytes_read)++] = tms9914_read_data_in(board, priv, end); - - if (check_for_eos(priv, buffer[*bytes_read - 1])) - *end = 1; - } - - return retval; -} - -int tms9914_read(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, - size_t length, int *end, size_t *bytes_read) -{ - ssize_t retval = 0; - size_t num_bytes; - - *end = 0; - *bytes_read = 0; - if (length == 0) - return 0; - - clear_bit(DEV_CLEAR_BN, &priv->state); - - // transfer data (except for last byte) - if (length > 1) { - if (priv->eos_flags & REOS) - tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_ALL); - else - tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_EOI); - // PIO transfer - retval = pio_read(board, priv, buffer, length - 1, end, &num_bytes); - *bytes_read += num_bytes; - if (retval < 0) - return retval; - buffer += num_bytes; - length -= num_bytes; - } - // read last bytes if we havn't received an END yet - if (*end == 0) { - // make sure we holdoff after last byte read - tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_ALL); - retval = pio_read(board, priv, buffer, length, end, &num_bytes); - *bytes_read += num_bytes; - if (retval < 0) - return retval; - } - return 0; -} -EXPORT_SYMBOL(tms9914_read); - -static int pio_write_wait(struct gpib_board *board, struct tms9914_priv *priv) -{ - // wait until next byte is ready to be sent - if (wait_event_interruptible(board->wait, - test_bit(WRITE_READY_BN, &priv->state) || - test_bit(BUS_ERROR_BN, &priv->state) || - test_bit(DEV_CLEAR_BN, &priv->state) || - test_bit(TIMO_NUM, &board->status))) - return -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - return -ETIMEDOUT; - if (test_bit(BUS_ERROR_BN, &priv->state)) - return -EIO; - if (test_bit(DEV_CLEAR_BN, &priv->state)) - return -EINTR; - - return 0; -} - -static int pio_write(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, - size_t length, size_t *bytes_written) -{ - ssize_t retval = 0; - unsigned long flags; - - *bytes_written = 0; - while (*bytes_written < length) { - retval = pio_write_wait(board, priv); - if (retval < 0) - break; - - spin_lock_irqsave(&board->spinlock, flags); - clear_bit(WRITE_READY_BN, &priv->state); - write_byte(priv, buffer[(*bytes_written)++], CDOR); - spin_unlock_irqrestore(&board->spinlock, flags); - } - retval = pio_write_wait(board, priv); - if (retval < 0) - return retval; - - return length; -} - -int tms9914_write(struct gpib_board *board, struct tms9914_priv *priv, - u8 *buffer, size_t length, int send_eoi, size_t *bytes_written) -{ - ssize_t retval = 0; - - *bytes_written = 0; - if (length == 0) - return 0; - - clear_bit(BUS_ERROR_BN, &priv->state); - clear_bit(DEV_CLEAR_BN, &priv->state); - - if (send_eoi) - length-- ; /* save the last byte for sending EOI */ - - if (length > 0) { - size_t num_bytes; - // PIO transfer - retval = pio_write(board, priv, buffer, length, &num_bytes); - *bytes_written += num_bytes; - if (retval < 0) - return retval; - } - if (send_eoi) { - size_t num_bytes; - /*send EOI */ - write_byte(priv, AUX_SEOI, AUXCR); - - retval = pio_write(board, priv, &buffer[*bytes_written], 1, &num_bytes); - *bytes_written += num_bytes; - } - return retval; -} -EXPORT_SYMBOL(tms9914_write); - -static void check_my_address_state(struct gpib_board *board, - struct tms9914_priv *priv, int cmd_byte) -{ - if (cmd_byte == MLA(board->pad)) { - priv->primary_listen_addressed = 1; - // become active listener - if (board->sad < 0) - write_byte(priv, AUX_LON | AUX_CS, AUXCR); - } else if (board->sad >= 0 && priv->primary_listen_addressed && - cmd_byte == MSA(board->sad)) { - // become active listener - write_byte(priv, AUX_LON | AUX_CS, AUXCR); - } else if (cmd_byte != MLA(board->pad) && (cmd_byte & 0xe0) == LAD) { - priv->primary_listen_addressed = 0; - } else if (cmd_byte == UNL) { - priv->primary_listen_addressed = 0; - write_byte(priv, AUX_LON, AUXCR); - } else if (cmd_byte == MTA(board->pad)) { - priv->primary_talk_addressed = 1; - if (board->sad < 0) - // make active talker - write_byte(priv, AUX_TON | AUX_CS, AUXCR); - } else if (board->sad >= 0 && priv->primary_talk_addressed && - cmd_byte == MSA(board->sad)) { - // become active talker - write_byte(priv, AUX_TON | AUX_CS, AUXCR); - } else if (cmd_byte != MTA(board->pad) && (cmd_byte & 0xe0) == TAD) { - // Other Talk Address - priv->primary_talk_addressed = 0; - write_byte(priv, AUX_TON, AUXCR); - } else if (cmd_byte == UNT) { - priv->primary_talk_addressed = 0; - write_byte(priv, AUX_TON, AUXCR); - } -} - -int tms9914_command(struct gpib_board *board, struct tms9914_priv *priv, u8 *buffer, - size_t length, size_t *bytes_written) -{ - int retval = 0; - unsigned long flags; - - *bytes_written = 0; - while (*bytes_written < length) { - if (wait_event_interruptible(board->wait, - test_bit(COMMAND_READY_BN, - &priv->state) || - test_bit(TIMO_NUM, &board->status))) - break; - if (test_bit(TIMO_NUM, &board->status)) - break; - - spin_lock_irqsave(&board->spinlock, flags); - clear_bit(COMMAND_READY_BN, &priv->state); - write_byte(priv, buffer[*bytes_written], CDOR); - spin_unlock_irqrestore(&board->spinlock, flags); - - check_my_address_state(board, priv, buffer[*bytes_written]); - - ++(*bytes_written); - } - // wait until last command byte is written - if (wait_event_interruptible(board->wait, - test_bit(COMMAND_READY_BN, - &priv->state) || test_bit(TIMO_NUM, &board->status))) - retval = -ERESTARTSYS; - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - - return retval; -} -EXPORT_SYMBOL(tms9914_command); - -irqreturn_t tms9914_interrupt(struct gpib_board *board, struct tms9914_priv *priv) -{ - int status0, status1; - - // read interrupt status (also clears status) - status0 = read_byte(priv, ISR0); - status1 = read_byte(priv, ISR1); - return tms9914_interrupt_have_status(board, priv, status0, status1); -} -EXPORT_SYMBOL(tms9914_interrupt); - -irqreturn_t tms9914_interrupt_have_status(struct gpib_board *board, struct tms9914_priv *priv, - int status0, int status1) -{ - // record reception of END - if (status0 & HR_END) - set_bit(RECEIVED_END_BN, &priv->state); - // get incoming data in PIO mode - if ((status0 & HR_BI)) - set_bit(READ_READY_BN, &priv->state); - if ((status0 & HR_BO)) { - if (read_byte(priv, ADSR) & HR_ATN) - set_bit(COMMAND_READY_BN, &priv->state); - else - set_bit(WRITE_READY_BN, &priv->state); - } - - if (status0 & HR_SPAS) { - priv->spoll_status &= ~request_service_bit; - write_byte(priv, priv->spoll_status, SPMR); - // FIXME: set SPOLL status bit - } - // record service request in status - if (status1 & HR_SRQ) - set_bit(SRQI_NUM, &board->status); - // have been addressed (with secondary addressing disabled) - if (status1 & HR_MA) - // clear dac holdoff - write_byte(priv, AUX_VAL, AUXCR); - // unrecognized command received - if (status1 & HR_UNC) { - unsigned short command_byte = read_byte(priv, CPTR) & gpib_command_mask; - - switch (command_byte) { - case PP_CONFIG: - priv->ppoll_configure_state = 1; - /* - * AUX_PTS generates another UNC interrupt on the next command byte - * if it is in the secondary address group (such as PPE and PPD). - */ - write_byte(priv, AUX_PTS, AUXCR); - write_byte(priv, AUX_VAL, AUXCR); - break; - case PPU: - tms9914_parallel_poll_configure(board, priv, command_byte); - write_byte(priv, AUX_VAL, AUXCR); - break; - default: - if (is_PPE(command_byte) || is_PPD(command_byte)) { - if (priv->ppoll_configure_state) { - tms9914_parallel_poll_configure(board, priv, command_byte); - write_byte(priv, AUX_VAL, AUXCR); - } else {// bad parallel poll configure byte - // clear dac holdoff - write_byte(priv, AUX_INVAL, AUXCR); - } - } else { - // clear dac holdoff - write_byte(priv, AUX_INVAL, AUXCR); - } - break; - } - - if (in_primary_command_group(command_byte) && command_byte != PP_CONFIG) - priv->ppoll_configure_state = 0; - } - - if (status1 & HR_ERR) { - dev_dbg(board->gpib_dev, "gpib bus error\n"); - set_bit(BUS_ERROR_BN, &priv->state); - } - - if (status1 & HR_IFC) { - push_gpib_event(board, EVENT_IFC); - clear_bit(CIC_NUM, &board->status); - } - - if (status1 & HR_GET) { - push_gpib_event(board, EVENT_DEV_TRG); - // clear dac holdoff - write_byte(priv, AUX_VAL, AUXCR); - } - - if (status1 & HR_DCAS) { - push_gpib_event(board, EVENT_DEV_CLR); - // clear dac holdoff - write_byte(priv, AUX_VAL, AUXCR); - set_bit(DEV_CLEAR_BN, &priv->state); - } - - // check for being addressed with secondary addressing - if (status1 & HR_APT) { - if (board->sad < 0) - dev_err(board->gpib_dev, "bug, APT interrupt without secondary addressing?\n"); - if ((read_byte(priv, CPTR) & gpib_command_mask) == MSA(board->sad)) - write_byte(priv, AUX_VAL, AUXCR); - else - write_byte(priv, AUX_INVAL, AUXCR); - } - - if ((status0 & priv->imr0_bits) || (status1 & priv->imr1_bits)) { - dev_dbg(board->gpib_dev, "isr0 0x%x, imr0 0x%x, isr1 0x%x, imr1 0x%x\n", - status0, priv->imr0_bits, status1, priv->imr1_bits); - update_status_nolock(board, priv); - wake_up_interruptible(&board->wait); - } - return IRQ_HANDLED; -} -EXPORT_SYMBOL(tms9914_interrupt_have_status); - -void tms9914_board_reset(struct tms9914_priv *priv) -{ - /* chip reset */ - write_byte(priv, AUX_CHIP_RESET | AUX_CS, AUXCR); - - /* disable all interrupts */ - priv->imr0_bits = 0; - write_byte(priv, priv->imr0_bits, IMR0); - priv->imr1_bits = 0; - write_byte(priv, priv->imr1_bits, IMR1); - write_byte(priv, AUX_DAI | AUX_CS, AUXCR); - - /* clear registers by reading */ - read_byte(priv, CPTR); - read_byte(priv, ISR0); - read_byte(priv, ISR1); - - write_byte(priv, 0, SPMR); - - /* parallel poll unconfigure */ - write_byte(priv, 0, PPR); - /* request for data holdoff */ - tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_ALL); -} -EXPORT_SYMBOL_GPL(tms9914_board_reset); - -void tms9914_online(struct gpib_board *board, struct tms9914_priv *priv) -{ - /* set GPIB address */ - tms9914_primary_address(board, priv, board->pad); - tms9914_secondary_address(board, priv, board->sad, board->sad >= 0); - - /* enable tms9914 interrupts */ - priv->imr0_bits |= HR_MACIE | HR_RLCIE | HR_ENDIE | HR_BOIE | HR_BIIE | - HR_SPASIE; - priv->imr1_bits |= HR_MAIE | HR_SRQIE | HR_UNCIE | HR_ERRIE | HR_IFCIE | - HR_GETIE | HR_DCASIE; - write_byte(priv, priv->imr0_bits, IMR0); - write_byte(priv, priv->imr1_bits, IMR1); - write_byte(priv, AUX_DAI, AUXCR); - - /* turn off reset state */ - write_byte(priv, AUX_CHIP_RESET, AUXCR); -} -EXPORT_SYMBOL_GPL(tms9914_online); - -#ifdef CONFIG_HAS_IOPORT -// wrapper for inb -u8 tms9914_ioport_read_byte(struct tms9914_priv *priv, unsigned int register_num) -{ - return inb(priv->iobase + register_num * priv->offset); -} -EXPORT_SYMBOL_GPL(tms9914_ioport_read_byte); - -// wrapper for outb -void tms9914_ioport_write_byte(struct tms9914_priv *priv, u8 data, unsigned int register_num) -{ - outb(data, priv->iobase + register_num * priv->offset); - if (register_num == AUXCR) - udelay(1); -} -EXPORT_SYMBOL_GPL(tms9914_ioport_write_byte); -#endif - -// wrapper for readb -u8 tms9914_iomem_read_byte(struct tms9914_priv *priv, unsigned int register_num) -{ - return readb(priv->mmiobase + register_num * priv->offset); -} -EXPORT_SYMBOL_GPL(tms9914_iomem_read_byte); - -// wrapper for writeb -void tms9914_iomem_write_byte(struct tms9914_priv *priv, u8 data, unsigned int register_num) -{ - writeb(data, priv->mmiobase + register_num * priv->offset); - if (register_num == AUXCR) - udelay(1); -} -EXPORT_SYMBOL_GPL(tms9914_iomem_write_byte); - -static int __init tms9914_init_module(void) -{ - return 0; -} - -static void __exit tms9914_exit_module(void) -{ -} - -module_init(tms9914_init_module); -module_exit(tms9914_exit_module); - diff --git a/drivers/staging/gpib/tnt4882/Makefile b/drivers/staging/gpib/tnt4882/Makefile deleted file mode 100644 index fa1687ad0d1b..000000000000 --- a/drivers/staging/gpib/tnt4882/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -obj-$(CONFIG_GPIB_NI_PCI_ISA) += tnt4882.o - -tnt4882-objs := tnt4882_gpib.o mite.o - - - diff --git a/drivers/staging/gpib/tnt4882/mite.c b/drivers/staging/gpib/tnt4882/mite.c deleted file mode 100644 index 847b96f411bd..000000000000 --- a/drivers/staging/gpib/tnt4882/mite.c +++ /dev/null @@ -1,133 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -/* - * Hardware driver for NI Mite PCI interface chip, - * adapted from COMEDI - * - * Copyright (C) 1997-8 David A. Schleef - * Copyright (C) 2002 Frank Mori Hess - * - * The PCI-MIO E series driver was originally written by - * Tomasz Motylewski <...>, and ported to comedi by ds. - * - * References for specifications: - * - * 321747b.pdf Register Level Programmer Manual (obsolete) - * 321747c.pdf Register Level Programmer Manual (new) - * DAQ-STC reference manual - * - * Other possibly relevant info: - * - * 320517c.pdf User manual (obsolete) - * 320517f.pdf User manual (new) - * 320889a.pdf delete - * 320906c.pdf maximum signal ratings - * 321066a.pdf about 16x - * 321791a.pdf discontinuation of at-mio-16e-10 rev. c - * 321808a.pdf about at-mio-16e-10 rev P - * 321837a.pdf discontinuation of at-mio-16de-10 rev d - * 321838a.pdf about at-mio-16de-10 rev N - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/io.h> -#include <linux/slab.h> - -#include "mite.h" - -#define PCI_MITE_SIZE 4096 -#define PCI_DAQ_SIZE 4096 - -struct mite_struct *mite_devices; - -#define TOP_OF_PAGE(x) ((x) | (~(PAGE_MASK))) - -void mite_init(void) -{ - struct pci_dev *pcidev; - struct mite_struct *mite; - - for (pcidev = pci_get_device(PCI_VENDOR_ID_NATINST, PCI_ANY_ID, NULL); - pcidev; - pcidev = pci_get_device(PCI_VENDOR_ID_NATINST, PCI_ANY_ID, pcidev)) { - mite = kzalloc(sizeof(*mite), GFP_KERNEL); - if (!mite) - return; - - mite->pcidev = pcidev; - pci_dev_get(mite->pcidev); - mite->next = mite_devices; - mite_devices = mite; - } -} - -int mite_setup(struct mite_struct *mite) -{ - u32 addr; - - if (pci_enable_device(mite->pcidev)) { - pr_err("mite: error enabling mite.\n"); - return -EIO; - } - pci_set_master(mite->pcidev); - if (pci_request_regions(mite->pcidev, "mite")) { - pr_err("mite: failed to request mite io regions.\n"); - return -EIO; - } - addr = pci_resource_start(mite->pcidev, 0); - mite->mite_phys_addr = addr; - mite->mite_io_addr = ioremap(addr, pci_resource_len(mite->pcidev, 0)); - if (!mite->mite_io_addr) { - pr_err("mite: failed to remap mite io memory address.\n"); - return -ENOMEM; - } - addr = pci_resource_start(mite->pcidev, 1); - mite->daq_phys_addr = addr; - mite->daq_io_addr = ioremap(mite->daq_phys_addr, pci_resource_len(mite->pcidev, 1)); - if (!mite->daq_io_addr) { - pr_err("mite: failed to remap daq io memory address.\n"); - return -ENOMEM; - } - writel(mite->daq_phys_addr | WENAB, mite->mite_io_addr + MITE_IODWBSR); - mite->used = 1; - return 0; -} - -void mite_cleanup(void) -{ - struct mite_struct *mite, *next; - - for (mite = mite_devices; mite; mite = next) { - next = mite->next; - if (mite->pcidev) - pci_dev_put(mite->pcidev); - kfree(mite); - } -} - -void mite_unsetup(struct mite_struct *mite) -{ - if (!mite) - return; - if (mite->mite_io_addr) { - iounmap(mite->mite_io_addr); - mite->mite_io_addr = NULL; - } - if (mite->daq_io_addr) { - iounmap(mite->daq_io_addr); - mite->daq_io_addr = NULL; - } - if (mite->mite_phys_addr) { - pci_release_regions(mite->pcidev); - pci_disable_device(mite->pcidev); - mite->mite_phys_addr = 0; - } - mite->used = 0; -} diff --git a/drivers/staging/gpib/tnt4882/mite.h b/drivers/staging/gpib/tnt4882/mite.h deleted file mode 100644 index a1fdba9672a0..000000000000 --- a/drivers/staging/gpib/tnt4882/mite.h +++ /dev/null @@ -1,234 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -/* - * Hardware driver for NI Mite PCI interface chip - * - * Copyright (C) 1999 David A. Schleef <ds@stm.lbl.gov> - */ - -#ifndef _MITE_H_ -#define _MITE_H_ - -#include <linux/pci.h> - -#define PCI_VENDOR_ID_NATINST 0x1093 - -//#define DEBUG_MITE - -#ifdef DEBUG_MITE -#define MDPRINTK(format, args...) pr_debug(format, ## args) -#else -#define MDPRINTK(args...) -#endif - -#define MITE_RING_SIZE 3000 -struct mite_dma_chain { - u32 count; - u32 addr; - u32 next; -}; - -struct mite_struct { - struct mite_struct *next; - int used; - - struct pci_dev *pcidev; - unsigned long mite_phys_addr; - void __iomem *mite_io_addr; - unsigned long daq_phys_addr; - void __iomem *daq_io_addr; - - int DMA_CheckNearEnd; - - struct mite_dma_chain ring[MITE_RING_SIZE]; -}; - -extern struct mite_struct *mite_devices; - -extern inline unsigned int mite_irq(struct mite_struct *mite) -{ - return mite->pcidev->irq; -}; - -extern inline unsigned int mite_device_id(struct mite_struct *mite) -{ - return mite->pcidev->device; -}; - -void mite_init(void); -void mite_cleanup(void); -int mite_setup(struct mite_struct *mite); -void mite_unsetup(struct mite_struct *mite); -void mite_list_devices(void); - -#define CHAN_OFFSET(x) (0x100 * (x)) - -/* DMA base for chan 0 is 0x500, chan 1 is 0x600 */ - -#define MITE_CHOR 0x500 -#define CHOR_DMARESET BIT(31) -#define CHOR_SET_SEND_TC BIT(11) -#define CHOR_CLR_SEND_TC BIT(10) -#define CHOR_SET_LPAUSE BIT(9) -#define CHOR_CLR_LPAUSE BIT(8) -#define CHOR_CLRDONE BIT(7) -#define CHOR_CLRRB BIT(6) -#define CHOR_CLRLC BIT(5) -#define CHOR_FRESET BIT(4) -#define CHOR_ABORT BIT(3) -#define CHOR_STOP BIT(2) -#define CHOR_CONT BIT(1) -#define CHOR_START BIT(0) -#define CHOR_PON (CHOR_CLR_SEND_TC | CHOR_CLR_LPAUSE) - -#define MITE_CHCR 0x504 -#define CHCR_SET_DMA_IE BIT(31) -#define CHCR_CLR_DMA_IE BIT(30) -#define CHCR_SET_LINKP_IE BIT(29) -#define CHCR_CLR_LINKP_IE BIT(28) -#define CHCR_SET_SAR_IE BIT(27) -#define CHCR_CLR_SAR_IE BIT(26) -#define CHCR_SET_DONE_IE BIT(25) -#define CHCR_CLR_DONE_IE BIT(24) -#define CHCR_SET_MRDY_IE BIT(23) -#define CHCR_CLR_MRDY_IE BIT(22) -#define CHCR_SET_DRDY_IE BIT(21) -#define CHCR_CLR_DRDY_IE BIT(20) -#define CHCR_SET_LC_IE BIT(19) -#define CHCR_CLR_LC_IE BIT(18) -#define CHCR_SET_CONT_RB_IE BIT(17) -#define CHCR_CLR_CONT_RB_IE BIT(16) -#define CHCR_FIFODIS BIT(15) -#define CHCR_FIFO_ON 0 -#define CHCR_BURSTEN BIT(14) -#define CHCR_NO_BURSTEN 0 -#define CHCR_NFTP(x) ((x) << 11) -#define CHCR_NFTP0 CHCR_NFTP(0) -#define CHCR_NFTP1 CHCR_NFTP(1) -#define CHCR_NFTP2 CHCR_NFTP(2) -#define CHCR_NFTP4 CHCR_NFTP(3) -#define CHCR_NFTP8 CHCR_NFTP(4) -#define CHCR_NFTP16 CHCR_NFTP(5) -#define CHCR_NETP(x) ((x) << 11) -#define CHCR_NETP0 CHCR_NETP(0) -#define CHCR_NETP1 CHCR_NETP(1) -#define CHCR_NETP2 CHCR_NETP(2) -#define CHCR_NETP4 CHCR_NETP(3) -#define CHCR_NETP8 CHCR_NETP(4) -#define CHCR_CHEND1 BIT(5) -#define CHCR_CHEND0 BIT(4) -#define CHCR_DIR BIT(3) -#define CHCR_DEV_TO_MEM CHCR_DIR -#define CHCR_MEM_TO_DEV 0 -#define CHCR_NORMAL ((0) << 0) -#define CHCR_CONTINUE ((1) << 0) -#define CHCR_RINGBUFF ((2) << 0) -#define CHCR_LINKSHORT ((4) << 0) -#define CHCR_LINKLONG ((5) << 0) -#define CHCRPON (CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE | CHCR_CLR_SAR_IE | \ - CHCR_CLR_DONE_IE | CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE | \ - CHCR_CLR_LC_IE | CHCR_CLR_CONT_IE) - -#define MITE_TCR 0x508 - -/* CR bits */ -#define CR_RL(x) ((x) << 21) -#define CR_RL0 CR_RL(0) -#define CR_RL1 CR_RL(1) -#define CR_RL2 CR_RL(2) -#define CR_RL4 CR_RL(3) -#define CR_RL8 CR_RL(4) -#define CR_RL16 CR_RL(5) -#define CR_RL32 CR_RL(6) -#define CR_RL64 CR_RL(7) -#define CR_RD(x) ((x) << 19) -#define CR_RD0 CR_RD(0) -#define CR_RD32 CR_RD(1) -#define CR_RD512 CR_RD(2) -#define CR_RD8192 CR_RD(3) -#define CR_REQS(x) ((x) << 16) -#define CR_REQSDRQ0 CR_REQS(4) -#define CR_REQSDRQ1 CR_REQS(5) -#define CR_REQSDRQ2 CR_REQS(6) -#define CR_REQSDRQ3 CR_REQS(7) -#define CR_ASEQX(x) ((x) << 10) -#define CR_ASEQX0 CR_ASEQX(0) -#define CR_ASEQDONT CR_ASEQX0 -#define CR_ASEQXP1 CR_ASEQX(1) -#define CR_ASEQUP CR_ASEQXP1 -#define CR_ASEQXP2 CR_ASEQX(2) -#define CR_ASEQDOWN CR_ASEQXP2 -#define CR_ASEQXP4 CR_ASEQX(3) -#define CR_ASEQXP8 CR_ASEQX(4) -#define CR_ASEQXP16 CR_ASEQX(5) -#define CR_ASEQXP32 CR_ASEQX(6) -#define CR_ASEQXP64 CR_ASEQX(7) -#define CR_ASEQXM1 CR_ASEQX(9) -#define CR_ASEQXM2 CR_ASEQX(10) -#define CR_ASEQXM4 CR_ASEQX(11) -#define CR_ASEQXM8 CR_ASEQX(12) -#define CR_ASEQXM16 CR_ASEQX(13) -#define CR_ASEQXM32 CR_ASEQX(14) -#define CR_ASEQXM64 CR_ASEQX(15) -#define CR_PSIZEBYTE BIT(8) -#define CR_PSIZEHALF (2 << 8) -#define CR_PSIZEWORD (3 << 8) -#define CR_PORTCPU (0 << 6) -#define CR_PORTIO BIT(6) -#define CR_PORTVXI (2 << 6) -#define CR_PORTMXI (3 << 6) -#define CR_AMDEVICE BIT(0) - -#define CHSR_INT 0x80000000 -#define CHSR_DONE 0x02000000 -#define CHSR_LINKC 0x00080000 - -#define MITE_MCR 0x50c -#define MCRPON 0 - -#define MITE_MAR 0x510 - -#define MITE_DCR 0x514 -#define DCR_NORMAL BIT(29) -#define DCRPON 0 - -#define MITE_DAR 0x518 - -#define MITE_LKCR 0x51c - -#define MITE_LKAR 0x520 -#define MITE_LLKAR 0x524 -#define MITE_BAR 0x528 -#define MITE_BCR 0x52c -#define MITE_SAR 0x530 -#define MITE_WSCR 0x534 -#define MITE_WSER 0x538 -#define MITE_CHSR 0x53c -#define MITE_FCR 0x540 - -#define MITE_FIFO 0x80 -#define MITE_FIFOEND 0xff - -#define MITE_AMRAM 0x00 -#define MITE_AMDEVICE 0x01 -#define MITE_AMHOST_A32_SINGLE 0x09 -#define MITE_AMHOST_A24_SINGLE 0x39 -#define MITE_AMHOST_A16_SINGLE 0x29 -#define MITE_AMHOST_A32_BLOCK 0x0b -#define MITE_AMHOST_A32D64_BLOCK 0x08 -#define MITE_AMHOST_A24_BLOCK 0x3b - -enum mite_registers { - MITE_IODWBSR = 0xc0, // IO Device Window Base Size Register - MITE_CSIGR = 0x460, // chip signature - MITE_IODWBSR_1 = 0xc4, // IO Device Window Base Size Register 1 (used by 6602 boards) - MITE_IODWCR_1 = 0xf4 -}; - -enum MITE_IODWBSR_bits { - WENAB = 0x80, // window enable - WENAB_6602 = 0x8c // window enable for 6602 boards -}; - -#endif - diff --git a/drivers/staging/gpib/tnt4882/tnt4882_gpib.c b/drivers/staging/gpib/tnt4882/tnt4882_gpib.c deleted file mode 100644 index c03a976b7380..000000000000 --- a/drivers/staging/gpib/tnt4882/tnt4882_gpib.c +++ /dev/null @@ -1,1838 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/*************************************************************************** - * National Instruments boards using tnt4882 or compatible chips (at-gpib, etc). - * copyright : (C) 2001, 2002 by Frank Mori Hess - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define dev_fmt pr_fmt -#define DRV_NAME KBUILD_MODNAME - -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/pci.h> -#include <linux/pci_ids.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/isapnp.h> - -#include "nec7210.h" -#include "gpibP.h" -#include "mite.h" -#include "tnt4882_registers.h" - -static const int ISAPNP_VENDOR_ID_NI = ISAPNP_VENDOR('N', 'I', 'C'); -static const int ISAPNP_ID_NI_ATGPIB_TNT = 0xc601; -enum { - PCI_DEVICE_ID_NI_GPIB = 0xc801, - PCI_DEVICE_ID_NI_GPIB_PLUS = 0xc811, - PCI_DEVICE_ID_NI_GPIB_PLUS2 = 0x71ad, - PCI_DEVICE_ID_NI_PXIGPIB = 0xc821, - PCI_DEVICE_ID_NI_PMCGPIB = 0xc831, - PCI_DEVICE_ID_NI_PCIEGPIB = 0x70cf, - PCI_DEVICE_ID_NI_PCIE2GPIB = 0x710e, -// Measurement Computing PCI-488 same design as PCI-GPIB with TNT5004 - PCI_DEVICE_ID_MC_PCI488 = 0x7259, - PCI_DEVICE_ID_CEC_NI_GPIB = 0x7258 -}; - -// struct which defines private_data for tnt4882 devices -struct tnt4882_priv { - struct nec7210_priv nec7210_priv; - struct mite_struct *mite; - struct pnp_dev *pnp_dev; - unsigned int irq; - unsigned short imr0_bits; - unsigned short imr3_bits; - unsigned short auxg_bits; // bits written to auxiliary register G -}; - -static irqreturn_t tnt4882_internal_interrupt(struct gpib_board *board); - -// register offset for nec7210 compatible registers -static const int atgpib_reg_offset = 2; - -// number of ioports used -static const int atgpib_iosize = 32; - -/* paged io */ -static inline unsigned int tnt_paged_readb(struct tnt4882_priv *priv, unsigned long offset) -{ - iowrite8(AUX_PAGEIN, priv->nec7210_priv.mmiobase + AUXMR * priv->nec7210_priv.offset); - udelay(1); - return ioread8(priv->nec7210_priv.mmiobase + offset); -} - -static inline void tnt_paged_writeb(struct tnt4882_priv *priv, unsigned int value, - unsigned long offset) -{ - iowrite8(AUX_PAGEIN, priv->nec7210_priv.mmiobase + AUXMR * priv->nec7210_priv.offset); - udelay(1); - iowrite8(value, priv->nec7210_priv.mmiobase + offset); -} - -/* readb/writeb wrappers */ -static inline unsigned short tnt_readb(struct tnt4882_priv *priv, unsigned long offset) -{ - void __iomem *address = priv->nec7210_priv.mmiobase + offset; - unsigned long flags; - unsigned short retval; - spinlock_t *register_lock = &priv->nec7210_priv.register_page_lock; - - spin_lock_irqsave(register_lock, flags); - switch (offset) { - case CSR: - case SASR: - case ISR0: - case BSR: - switch (priv->nec7210_priv.type) { - case TNT4882: - case TNT5004: - retval = ioread8(address); - break; - case NAT4882: - retval = tnt_paged_readb(priv, offset - tnt_pagein_offset); - break; - case NEC7210: - retval = 0; - break; - default: - retval = 0; - break; - } - break; - default: - retval = ioread8(address); - break; - } - spin_unlock_irqrestore(register_lock, flags); - return retval; -} - -static inline void tnt_writeb(struct tnt4882_priv *priv, unsigned short value, unsigned long offset) -{ - void __iomem *address = priv->nec7210_priv.mmiobase + offset; - unsigned long flags; - spinlock_t *register_lock = &priv->nec7210_priv.register_page_lock; - - spin_lock_irqsave(register_lock, flags); - switch (offset) { - case KEYREG: - case IMR0: - case BCR: - switch (priv->nec7210_priv.type) { - case TNT4882: - case TNT5004: - iowrite8(value, address); - break; - case NAT4882: - tnt_paged_writeb(priv, value, offset - tnt_pagein_offset); - break; - case NEC7210: - break; - default: - break; - } - break; - default: - iowrite8(value, address); - break; - } - spin_unlock_irqrestore(register_lock, flags); -} - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("GPIB driver for National Instruments boards using tnt4882 or compatible chips"); - -static int tnt4882_line_status(const struct gpib_board *board) -{ - int status = VALID_ALL; - int bcsr_bits; - struct tnt4882_priv *tnt_priv; - - tnt_priv = board->private_data; - - bcsr_bits = tnt_readb(tnt_priv, BSR); - - if (bcsr_bits & BCSR_REN_BIT) - status |= BUS_REN; - if (bcsr_bits & BCSR_IFC_BIT) - status |= BUS_IFC; - if (bcsr_bits & BCSR_SRQ_BIT) - status |= BUS_SRQ; - if (bcsr_bits & BCSR_EOI_BIT) - status |= BUS_EOI; - if (bcsr_bits & BCSR_NRFD_BIT) - status |= BUS_NRFD; - if (bcsr_bits & BCSR_NDAC_BIT) - status |= BUS_NDAC; - if (bcsr_bits & BCSR_DAV_BIT) - status |= BUS_DAV; - if (bcsr_bits & BCSR_ATN_BIT) - status |= BUS_ATN; - - return status; -} - -static int tnt4882_t1_delay(struct gpib_board *board, unsigned int nano_sec) -{ - struct tnt4882_priv *tnt_priv = board->private_data; - struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; - unsigned int retval; - - retval = nec7210_t1_delay(board, nec_priv, nano_sec); - if (nec_priv->type == NEC7210) - return retval; - - if (nano_sec <= 350) { - tnt_writeb(tnt_priv, MSTD, KEYREG); - retval = 350; - } else { - tnt_writeb(tnt_priv, 0, KEYREG); - } - if (nano_sec > 500 && nano_sec <= 1100) { - write_byte(nec_priv, AUXRI | USTD, AUXMR); - retval = 1100; - } else { - write_byte(nec_priv, AUXRI, AUXMR); - } - return retval; -} - -static int fifo_word_available(struct tnt4882_priv *tnt_priv) -{ - int status2; - int retval; - - status2 = tnt_readb(tnt_priv, STS2); - retval = (status2 & AEFN) && (status2 & BEFN); - - return retval; -} - -static int fifo_byte_available(struct tnt4882_priv *tnt_priv) -{ - int status2; - int retval; - - status2 = tnt_readb(tnt_priv, STS2); - retval = (status2 & AEFN) || (status2 & BEFN); - - return retval; -} - -static int fifo_xfer_done(struct tnt4882_priv *tnt_priv) -{ - int status1; - int retval; - - status1 = tnt_readb(tnt_priv, STS1); - retval = status1 & (S_DONE | S_HALT); - - return retval; -} - -static int drain_fifo_words(struct tnt4882_priv *tnt_priv, u8 *buffer, int num_bytes) -{ - int count = 0; - struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; - - while (fifo_word_available(tnt_priv) && count + 2 <= num_bytes) { - short word; - - word = ioread16(nec_priv->mmiobase + FIFOB); - buffer[count++] = word & 0xff; - buffer[count++] = (word >> 8) & 0xff; - } - return count; -} - -static void tnt4882_release_holdoff(struct gpib_board *board, struct tnt4882_priv *tnt_priv) -{ - struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; - unsigned short sasr_bits; - - sasr_bits = tnt_readb(tnt_priv, SASR); - - /* - * tnt4882 not in one-chip mode won't always release holdoff unless we - * are in the right mode when release handshake command is given - */ - if (sasr_bits & AEHS_BIT) /* holding off due to holdoff on end mode*/ { - nec7210_set_handshake_mode(board, nec_priv, HR_HLDE); - write_byte(nec_priv, AUX_FH, AUXMR); - } else if (sasr_bits & ANHS1_BIT) { /* held off due to holdoff on all data mode*/ - nec7210_set_handshake_mode(board, nec_priv, HR_HLDA); - write_byte(nec_priv, AUX_FH, AUXMR); - nec7210_set_handshake_mode(board, nec_priv, HR_HLDE); - } else { /* held off due to holdoff immediately command */ - nec7210_set_handshake_mode(board, nec_priv, HR_HLDE); - write_byte(nec_priv, AUX_FH, AUXMR); - } -} - -static int tnt4882_accel_read(struct gpib_board *board, u8 *buffer, size_t length, int *end, - size_t *bytes_read) -{ - size_t count = 0; - ssize_t retval = 0; - struct tnt4882_priv *tnt_priv = board->private_data; - struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; - unsigned int bits; - s32 hw_count; - unsigned long flags; - - *bytes_read = 0; - // FIXME: really, DEV_CLEAR_BN should happen elsewhere to prevent race - clear_bit(DEV_CLEAR_BN, &nec_priv->state); - clear_bit(ADR_CHANGE_BN, &nec_priv->state); - - nec7210_set_reg_bits(nec_priv, IMR1, HR_ENDIE, HR_ENDIE); - if (nec_priv->type != TNT4882 && nec_priv->type != TNT5004) - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI); - else - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); - tnt_writeb(tnt_priv, nec_priv->auxa_bits | HR_HLDA, CCR); - bits = TNT_B_16BIT | TNT_IN | TNT_CCEN; - tnt_writeb(tnt_priv, bits, CFG); - tnt_writeb(tnt_priv, RESET_FIFO, CMDR); - udelay(1); - // load 2's complement of count into hardware counters - hw_count = -length; - tnt_writeb(tnt_priv, hw_count & 0xff, CNT0); - tnt_writeb(tnt_priv, (hw_count >> 8) & 0xff, CNT1); - tnt_writeb(tnt_priv, (hw_count >> 16) & 0xff, CNT2); - tnt_writeb(tnt_priv, (hw_count >> 24) & 0xff, CNT3); - - tnt4882_release_holdoff(board, tnt_priv); - - tnt_writeb(tnt_priv, GO, CMDR); - udelay(1); - - spin_lock_irqsave(&board->spinlock, flags); - tnt_priv->imr3_bits |= HR_DONE | HR_NEF; - tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); - spin_unlock_irqrestore(&board->spinlock, flags); - - while (count + 2 <= length && - test_bit(RECEIVED_END_BN, &nec_priv->state) == 0 && - fifo_xfer_done(tnt_priv) == 0) { - // wait until a word is ready - if (wait_event_interruptible(board->wait, - fifo_word_available(tnt_priv) || - fifo_xfer_done(tnt_priv) || - test_bit(RECEIVED_END_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(ADR_CHANGE_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - retval = -ERESTARTSYS; - break; - } - if (test_bit(TIMO_NUM, &board->status)) { - retval = -ETIMEDOUT; - break; - } - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) { - retval = -EINTR; - break; - } - if (test_bit(ADR_CHANGE_BN, &nec_priv->state)) { - retval = -EINTR; - break; - } - - spin_lock_irqsave(&board->spinlock, flags); - count += drain_fifo_words(tnt_priv, &buffer[count], length - count); - tnt_priv->imr3_bits |= HR_NEF; - tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); - spin_unlock_irqrestore(&board->spinlock, flags); - - if (need_resched()) - schedule(); - } - // wait for last byte - if (count < length) { - spin_lock_irqsave(&board->spinlock, flags); - tnt_priv->imr3_bits |= HR_DONE | HR_NEF; - tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); - spin_unlock_irqrestore(&board->spinlock, flags); - - if (wait_event_interruptible(board->wait, - fifo_xfer_done(tnt_priv) || - test_bit(RECEIVED_END_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(ADR_CHANGE_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) { - retval = -ERESTARTSYS; - } - if (test_bit(TIMO_NUM, &board->status)) - retval = -ETIMEDOUT; - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) - retval = -EINTR; - if (test_bit(ADR_CHANGE_BN, &nec_priv->state)) - retval = -EINTR; - count += drain_fifo_words(tnt_priv, &buffer[count], length - count); - if (fifo_byte_available(tnt_priv) && count < length) - buffer[count++] = tnt_readb(tnt_priv, FIFOB); - } - if (count < length) - tnt_writeb(tnt_priv, STOP, CMDR); - udelay(1); - - nec7210_set_reg_bits(nec_priv, IMR1, HR_ENDIE, 0); - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0); - /* - * force handling of any pending interrupts (seems to be needed - * to keep interrupts from getting hosed, plus for syncing - * with RECEIVED_END below) - */ - tnt4882_internal_interrupt(board); - /* RECEIVED_END should be in sync now */ - if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state)) - *end = 1; - if (retval < 0) { - // force immediate holdoff - write_byte(nec_priv, AUX_HLDI, AUXMR); - - set_bit(RFD_HOLDOFF_BN, &nec_priv->state); - } - *bytes_read = count; - - return retval; -} - -static int fifo_space_available(struct tnt4882_priv *tnt_priv) -{ - int status2; - int retval; - - status2 = tnt_readb(tnt_priv, STS2); - retval = (status2 & AFFN) && (status2 & BFFN); - - return retval; -} - -static unsigned int tnt_transfer_count(struct tnt4882_priv *tnt_priv) -{ - unsigned int count = 0; - - count |= tnt_readb(tnt_priv, CNT0) & 0xff; - count |= (tnt_readb(tnt_priv, CNT1) << 8) & 0xff00; - count |= (tnt_readb(tnt_priv, CNT2) << 16) & 0xff0000; - count |= (tnt_readb(tnt_priv, CNT3) << 24) & 0xff000000; - // return two's complement - return -count; -}; - -static int write_wait(struct gpib_board *board, struct tnt4882_priv *tnt_priv, - int wait_for_done, int send_commands) -{ - struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; - - if (wait_event_interruptible(board->wait, - (!wait_for_done && fifo_space_available(tnt_priv)) || - fifo_xfer_done(tnt_priv) || - test_bit(BUS_ERROR_BN, &nec_priv->state) || - test_bit(DEV_CLEAR_BN, &nec_priv->state) || - test_bit(TIMO_NUM, &board->status))) - return -ERESTARTSYS; - - if (test_bit(TIMO_NUM, &board->status)) - return -ETIMEDOUT; - if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state)) - return (send_commands) ? -ENOTCONN : -ECOMM; - if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) - return -EINTR; - return 0; -} - -static int generic_write(struct gpib_board *board, u8 *buffer, size_t length, - int send_eoi, int send_commands, size_t *bytes_written) -{ - size_t count = 0; - ssize_t retval = 0; - struct tnt4882_priv *tnt_priv = board->private_data; - struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; - unsigned int bits; - s32 hw_count; - unsigned long flags; - - *bytes_written = 0; - // FIXME: really, DEV_CLEAR_BN should happen elsewhere to prevent race - clear_bit(DEV_CLEAR_BN, &nec_priv->state); - - nec7210_set_reg_bits(nec_priv, IMR1, HR_ERRIE, HR_ERRIE); - - if (nec_priv->type != TNT4882 && nec_priv->type != TNT5004) - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO); - else - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0); - - tnt_writeb(tnt_priv, RESET_FIFO, CMDR); - udelay(1); - - bits = TNT_B_16BIT; - if (send_eoi) { - bits |= TNT_CCEN; - if (nec_priv->type != TNT4882 && nec_priv->type != TNT5004) - tnt_writeb(tnt_priv, AUX_SEOI, CCR); - } - if (send_commands) - bits |= TNT_COMMAND; - tnt_writeb(tnt_priv, bits, CFG); - - // load 2's complement of count into hardware counters - hw_count = -length; - tnt_writeb(tnt_priv, hw_count & 0xff, CNT0); - tnt_writeb(tnt_priv, (hw_count >> 8) & 0xff, CNT1); - tnt_writeb(tnt_priv, (hw_count >> 16) & 0xff, CNT2); - tnt_writeb(tnt_priv, (hw_count >> 24) & 0xff, CNT3); - - tnt_writeb(tnt_priv, GO, CMDR); - udelay(1); - - spin_lock_irqsave(&board->spinlock, flags); - tnt_priv->imr3_bits |= HR_DONE; - tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); - spin_unlock_irqrestore(&board->spinlock, flags); - - while (count < length) { - // wait until byte is ready to be sent - retval = write_wait(board, tnt_priv, 0, send_commands); - if (retval < 0) - break; - if (fifo_xfer_done(tnt_priv)) - break; - spin_lock_irqsave(&board->spinlock, flags); - while (fifo_space_available(tnt_priv) && count < length) { - u16 word; - - word = buffer[count++] & 0xff; - if (count < length) - word |= (buffer[count++] << 8) & 0xff00; - iowrite16(word, nec_priv->mmiobase + FIFOB); - } -// avoid unnecessary HR_NFF interrupts -// tnt_priv->imr3_bits |= HR_NFF; -// tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); - spin_unlock_irqrestore(&board->spinlock, flags); - - if (need_resched()) - schedule(); - } - // wait last byte has been sent - if (retval == 0) - retval = write_wait(board, tnt_priv, 1, send_commands); - - tnt_writeb(tnt_priv, STOP, CMDR); - udelay(1); - - nec7210_set_reg_bits(nec_priv, IMR1, HR_ERR, 0x0); - nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0x0); - /* - * force handling of any interrupts that happened - * while they were masked (this appears to be needed) - */ - tnt4882_internal_interrupt(board); - *bytes_written = length - tnt_transfer_count(tnt_priv); - return retval; -} - -static int tnt4882_accel_write(struct gpib_board *board, u8 *buffer, - size_t length, int send_eoi, size_t *bytes_written) -{ - return generic_write(board, buffer, length, send_eoi, 0, bytes_written); -} - -static int tnt4882_command(struct gpib_board *board, u8 *buffer, size_t length, - size_t *bytes_written) -{ - return generic_write(board, buffer, length, 0, 1, bytes_written); -} - -static irqreturn_t tnt4882_internal_interrupt(struct gpib_board *board) -{ - struct tnt4882_priv *priv = board->private_data; - int isr0_bits, isr3_bits, imr3_bits; - unsigned long flags; - - spin_lock_irqsave(&board->spinlock, flags); - - nec7210_interrupt(board, &priv->nec7210_priv); - - isr0_bits = tnt_readb(priv, ISR0); - isr3_bits = tnt_readb(priv, ISR3); - imr3_bits = priv->imr3_bits; - - if (isr0_bits & TNT_IFCI_BIT) - push_gpib_event(board, EVENT_IFC); - // XXX don't need this wakeup, one below should do? -// wake_up_interruptible(&board->wait); - - if (isr3_bits & HR_NFF) - priv->imr3_bits &= ~HR_NFF; - if (isr3_bits & HR_NEF) - priv->imr3_bits &= ~HR_NEF; - if (isr3_bits & HR_DONE) - priv->imr3_bits &= ~HR_DONE; - if (isr3_bits & (HR_INTR | HR_TLCI)) { - dev_dbg(board->gpib_dev, "minor %i isr0 0x%x imr0 0x%x isr3 0x%x imr3 0x%x\n", - board->minor, isr0_bits, priv->imr0_bits, isr3_bits, imr3_bits); - tnt_writeb(priv, priv->imr3_bits, IMR3); - wake_up_interruptible(&board->wait); - } - spin_unlock_irqrestore(&board->spinlock, flags); - return IRQ_HANDLED; -} - -static irqreturn_t tnt4882_interrupt(int irq, void *arg) -{ - return tnt4882_internal_interrupt(arg); -} - -// wrappers for interface functions -static int tnt4882_read(struct gpib_board *board, u8 *buffer, size_t length, int *end, - size_t *bytes_read) -{ - struct tnt4882_priv *priv = board->private_data; - struct nec7210_priv *nec_priv = &priv->nec7210_priv; - int retval; - int dummy; - - retval = nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read); - - if (retval < 0) { // force immediate holdoff - write_byte(nec_priv, AUX_HLDI, AUXMR); - - set_bit(RFD_HOLDOFF_BN, &nec_priv->state); - - nec7210_read_data_in(board, nec_priv, &dummy); - } - return retval; -} - -static int tnt4882_write(struct gpib_board *board, u8 *buffer, size_t length, int send_eoi, - size_t *bytes_written) -{ - struct tnt4882_priv *priv = board->private_data; - - return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written); -} - -static int tnt4882_command_unaccel(struct gpib_board *board, u8 *buffer, - size_t length, size_t *bytes_written) -{ - struct tnt4882_priv *priv = board->private_data; - - return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written); -} - -static int tnt4882_take_control(struct gpib_board *board, int synchronous) -{ - struct tnt4882_priv *priv = board->private_data; - - return nec7210_take_control(board, &priv->nec7210_priv, synchronous); -} - -static int tnt4882_go_to_standby(struct gpib_board *board) -{ - struct tnt4882_priv *priv = board->private_data; - - return nec7210_go_to_standby(board, &priv->nec7210_priv); -} - -static int tnt4882_request_system_control(struct gpib_board *board, int request_control) -{ - struct tnt4882_priv *priv = board->private_data; - int retval; - - if (request_control) { - tnt_writeb(priv, SETSC, CMDR); - udelay(1); - } - retval = nec7210_request_system_control(board, &priv->nec7210_priv, request_control); - if (!request_control) { - tnt_writeb(priv, CLRSC, CMDR); - udelay(1); - } - return retval; -} - -static void tnt4882_interface_clear(struct gpib_board *board, int assert) -{ - struct tnt4882_priv *priv = board->private_data; - - nec7210_interface_clear(board, &priv->nec7210_priv, assert); -} - -static void tnt4882_remote_enable(struct gpib_board *board, int enable) -{ - struct tnt4882_priv *priv = board->private_data; - - nec7210_remote_enable(board, &priv->nec7210_priv, enable); -} - -static int tnt4882_enable_eos(struct gpib_board *board, u8 eos_byte, int compare_8_bits) -{ - struct tnt4882_priv *priv = board->private_data; - - return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits); -} - -static void tnt4882_disable_eos(struct gpib_board *board) -{ - struct tnt4882_priv *priv = board->private_data; - - nec7210_disable_eos(board, &priv->nec7210_priv); -} - -static unsigned int tnt4882_update_status(struct gpib_board *board, unsigned int clear_mask) -{ - unsigned long flags; - u8 line_status; - struct tnt4882_priv *priv = board->private_data; - - spin_lock_irqsave(&board->spinlock, flags); - board->status &= ~clear_mask; - nec7210_update_status_nolock(board, &priv->nec7210_priv); - /* set / clear SRQ state since it is not cleared by interrupt */ - line_status = tnt_readb(priv, BSR); - if (line_status & BCSR_SRQ_BIT) - set_bit(SRQI_NUM, &board->status); - else - clear_bit(SRQI_NUM, &board->status); - spin_unlock_irqrestore(&board->spinlock, flags); - return board->status; -} - -static int tnt4882_primary_address(struct gpib_board *board, unsigned int address) -{ - struct tnt4882_priv *priv = board->private_data; - - return nec7210_primary_address(board, &priv->nec7210_priv, address); -} - -static int tnt4882_secondary_address(struct gpib_board *board, unsigned int address, int enable) -{ - struct tnt4882_priv *priv = board->private_data; - - return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable); -} - -static int tnt4882_parallel_poll(struct gpib_board *board, u8 *result) -{ - struct tnt4882_priv *tnt_priv = board->private_data; - - if (tnt_priv->nec7210_priv.type != NEC7210) { - tnt_priv->auxg_bits |= RPP2_BIT; - write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR); - udelay(2); // FIXME use parallel poll timeout - *result = read_byte(&tnt_priv->nec7210_priv, CPTR); - tnt_priv->auxg_bits &= ~RPP2_BIT; - write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR); - return 0; - } else { - return nec7210_parallel_poll(board, &tnt_priv->nec7210_priv, result); - } -} - -static void tnt4882_parallel_poll_configure(struct gpib_board *board, u8 config) -{ - struct tnt4882_priv *priv = board->private_data; - - if (priv->nec7210_priv.type == TNT5004) { - /* configure locally */ - write_byte(&priv->nec7210_priv, AUXRI | 0x4, AUXMR); - if (config) - /* set response + clear sense */ - write_byte(&priv->nec7210_priv, PPR | config, AUXMR); - else - /* disable ppoll */ - write_byte(&priv->nec7210_priv, PPR | 0x10, AUXMR); - } else { - nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config); - } -} - -static void tnt4882_parallel_poll_response(struct gpib_board *board, int ist) -{ - struct tnt4882_priv *priv = board->private_data; - - nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist); -} - -/* - * this is just used by the old nec7210 isa interfaces, the newer - * boards use tnt4882_serial_poll_response2 - */ -static void tnt4882_serial_poll_response(struct gpib_board *board, u8 status) -{ - struct tnt4882_priv *priv = board->private_data; - - nec7210_serial_poll_response(board, &priv->nec7210_priv, status); -} - -static void tnt4882_serial_poll_response2(struct gpib_board *board, u8 status, - int new_reason_for_service) -{ - struct tnt4882_priv *priv = board->private_data; - unsigned long flags; - const int MSS = status & request_service_bit; - const int reqt = MSS && new_reason_for_service; - const int reqf = MSS == 0; - - spin_lock_irqsave(&board->spinlock, flags); - if (reqt) { - priv->nec7210_priv.srq_pending = 1; - clear_bit(SPOLL_NUM, &board->status); - } else { - if (reqf) - priv->nec7210_priv.srq_pending = 0; - } - if (reqt) - /* - * It may seem like a race to issue reqt before updating - * the status byte, but it is not. The chip does not - * issue the reqt until the SPMR is written to at - * a later time. - */ - write_byte(&priv->nec7210_priv, AUX_REQT, AUXMR); - else if (reqf) - write_byte(&priv->nec7210_priv, AUX_REQF, AUXMR); - /* - * We need to always zero bit 6 of the status byte before writing it to - * the SPMR to insure we are using - * serial poll mode SP1, and not accidentally triggering mode SP3. - */ - write_byte(&priv->nec7210_priv, status & ~request_service_bit, SPMR); - spin_unlock_irqrestore(&board->spinlock, flags); -} - -static u8 tnt4882_serial_poll_status(struct gpib_board *board) -{ - struct tnt4882_priv *priv = board->private_data; - - return nec7210_serial_poll_status(board, &priv->nec7210_priv); -} - -static void tnt4882_return_to_local(struct gpib_board *board) -{ - struct tnt4882_priv *priv = board->private_data; - - nec7210_return_to_local(board, &priv->nec7210_priv); -} - -static void tnt4882_board_reset(struct tnt4882_priv *tnt_priv, struct gpib_board *board) -{ - struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; - - tnt_priv->imr0_bits = 0; - tnt_writeb(tnt_priv, tnt_priv->imr0_bits, IMR0); - tnt_priv->imr3_bits = 0; - tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); - tnt_readb(tnt_priv, IMR0); - tnt_readb(tnt_priv, IMR3); - nec7210_board_reset(nec_priv, board); -} - -static int tnt4882_allocate_private(struct gpib_board *board) -{ - struct tnt4882_priv *tnt_priv; - - board->private_data = kmalloc(sizeof(struct tnt4882_priv), GFP_KERNEL); - if (!board->private_data) - return -1; - tnt_priv = board->private_data; - memset(tnt_priv, 0, sizeof(struct tnt4882_priv)); - init_nec7210_private(&tnt_priv->nec7210_priv); - return 0; -} - -static void tnt4882_free_private(struct gpib_board *board) -{ - kfree(board->private_data); - board->private_data = NULL; -} - -static void tnt4882_init(struct tnt4882_priv *tnt_priv, const struct gpib_board *board) -{ - struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv; - - /* Turbo488 software reset */ - tnt_writeb(tnt_priv, SOFT_RESET, CMDR); - udelay(1); - - // turn off one-chip mode - tnt_writeb(tnt_priv, NODMA, HSSEL); - tnt_writeb(tnt_priv, 0, ACCWR); - // make sure we are in 7210 mode - tnt_writeb(tnt_priv, AUX_7210, AUXCR); - udelay(1); - // registers might be swapped, so write it to the swapped address too - tnt_writeb(tnt_priv, AUX_7210, SWAPPED_AUXCR); - udelay(1); - // turn on one-chip mode - if (nec_priv->type == TNT4882 || nec_priv->type == TNT5004) - tnt_writeb(tnt_priv, NODMA | TNT_ONE_CHIP_BIT, HSSEL); - else - tnt_writeb(tnt_priv, NODMA, HSSEL); - - nec7210_board_reset(nec_priv, board); - // read-clear isr0 - tnt_readb(tnt_priv, ISR0); - - // enable passing of nat4882 interrupts - tnt_priv->imr3_bits = HR_TLCI; - tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3); - - // enable interrupt - tnt_writeb(tnt_priv, 0x1, INTRT); - - // force immediate holdoff - write_byte(&tnt_priv->nec7210_priv, AUX_HLDI, AUXMR); - - set_bit(RFD_HOLDOFF_BN, &nec_priv->state); - - tnt_priv->auxg_bits = AUXRG | NTNL_BIT; - write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR); - - nec7210_board_online(nec_priv, board); - // enable interface clear interrupt for event queue - tnt_priv->imr0_bits = TNT_IMR0_ALWAYS_BITS | TNT_ATNI_BIT | TNT_IFCIE_BIT; - tnt_writeb(tnt_priv, tnt_priv->imr0_bits, IMR0); -} - -static int ni_pci_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct tnt4882_priv *tnt_priv; - struct nec7210_priv *nec_priv; - int isr_flags = IRQF_SHARED; - int retval; - struct mite_struct *mite; - - board->status = 0; - - if (tnt4882_allocate_private(board)) - return -ENOMEM; - tnt_priv = board->private_data; - nec_priv = &tnt_priv->nec7210_priv; - nec_priv->type = TNT4882; - nec_priv->read_byte = nec7210_locking_iomem_read_byte; - nec_priv->write_byte = nec7210_locking_iomem_write_byte; - nec_priv->offset = atgpib_reg_offset; - - if (!mite_devices) - return -ENODEV; - - for (mite = mite_devices; mite; mite = mite->next) { - short found_board; - - if (mite->used) - continue; - if (config->pci_bus >= 0 && config->pci_bus != mite->pcidev->bus->number) - continue; - if (config->pci_slot >= 0 && config->pci_slot != PCI_SLOT(mite->pcidev->devfn)) - continue; - switch (mite_device_id(mite)) { - case PCI_DEVICE_ID_NI_GPIB: - case PCI_DEVICE_ID_NI_GPIB_PLUS: - case PCI_DEVICE_ID_NI_GPIB_PLUS2: - case PCI_DEVICE_ID_NI_PXIGPIB: - case PCI_DEVICE_ID_NI_PMCGPIB: - case PCI_DEVICE_ID_NI_PCIEGPIB: - case PCI_DEVICE_ID_NI_PCIE2GPIB: -// support for Measurement Computing PCI-488 - case PCI_DEVICE_ID_MC_PCI488: - case PCI_DEVICE_ID_CEC_NI_GPIB: - found_board = 1; - break; - default: - found_board = 0; - break; - } - if (found_board) - break; - } - if (!mite) - return -ENODEV; - - tnt_priv->mite = mite; - retval = mite_setup(tnt_priv->mite); - if (retval < 0) - return retval; - - nec_priv->mmiobase = tnt_priv->mite->daq_io_addr; - - // get irq - retval = request_irq(mite_irq(tnt_priv->mite), tnt4882_interrupt, isr_flags, "ni-pci-gpib", - board); - if (retval) { - dev_err(board->gpib_dev, "failed to obtain pci irq %d\n", mite_irq(tnt_priv->mite)); - return retval; - } - tnt_priv->irq = mite_irq(tnt_priv->mite); - - // TNT5004 detection - switch (tnt_readb(tnt_priv, CSR) & 0xf0) { - case 0x30: - nec_priv->type = TNT4882; - break; - case 0x40: - nec_priv->type = TNT5004; - break; - } - tnt4882_init(tnt_priv, board); - - return 0; -} - -static void ni_pci_detach(struct gpib_board *board) -{ - struct tnt4882_priv *tnt_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (tnt_priv) { - nec_priv = &tnt_priv->nec7210_priv; - - if (nec_priv->mmiobase) - tnt4882_board_reset(tnt_priv, board); - if (tnt_priv->irq) - free_irq(tnt_priv->irq, board); - if (tnt_priv->mite) - mite_unsetup(tnt_priv->mite); - } - tnt4882_free_private(board); -} - -static int ni_isapnp_find(struct pnp_dev **dev) -{ - *dev = pnp_find_dev(NULL, ISAPNP_VENDOR_ID_NI, - ISAPNP_FUNCTION(ISAPNP_ID_NI_ATGPIB_TNT), NULL); - if (!*dev || !(*dev)->card) - return -ENODEV; - if (pnp_device_attach(*dev) < 0) - return -EBUSY; - if (pnp_activate_dev(*dev) < 0) { - pnp_device_detach(*dev); - return -EAGAIN; - } - if (!pnp_port_valid(*dev, 0) || !pnp_irq_valid(*dev, 0)) { - pnp_device_detach(*dev); - return -EINVAL; - } - return 0; -} - -static int ni_isa_attach_common(struct gpib_board *board, const struct gpib_board_config *config, - enum nec7210_chipset chipset) -{ - struct tnt4882_priv *tnt_priv; - struct nec7210_priv *nec_priv; - int isr_flags = 0; - u32 iobase; - int irq; - int retval; - - board->status = 0; - - if (tnt4882_allocate_private(board)) - return -ENOMEM; - tnt_priv = board->private_data; - nec_priv = &tnt_priv->nec7210_priv; - nec_priv->type = chipset; - nec_priv->read_byte = nec7210_locking_ioport_read_byte; - nec_priv->write_byte = nec7210_locking_ioport_write_byte; - nec_priv->offset = atgpib_reg_offset; - - // look for plug-n-play board - if (config->ibbase == 0) { - struct pnp_dev *dev; - - retval = ni_isapnp_find(&dev); - if (retval < 0) - return retval; - tnt_priv->pnp_dev = dev; - iobase = pnp_port_start(dev, 0); - irq = pnp_irq(dev, 0); - } else { - iobase = config->ibbase; - irq = config->ibirq; - } - // allocate ioports - if (!request_region(iobase, atgpib_iosize, "atgpib")) - return -EBUSY; - - nec_priv->mmiobase = ioport_map(iobase, atgpib_iosize); - if (!nec_priv->mmiobase) - return -EBUSY; - - // get irq - retval = request_irq(irq, tnt4882_interrupt, isr_flags, "atgpib", board); - if (retval) { - dev_err(board->gpib_dev, "failed to request ISA irq %d\n", irq); - return retval; - } - tnt_priv->irq = irq; - - tnt4882_init(tnt_priv, board); - - return 0; -} - -static int ni_tnt_isa_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - return ni_isa_attach_common(board, config, TNT4882); -} - -static int ni_nat4882_isa_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - return ni_isa_attach_common(board, config, NAT4882); -} - -static int ni_nec_isa_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - return ni_isa_attach_common(board, config, NEC7210); -} - -static void ni_isa_detach(struct gpib_board *board) -{ - struct tnt4882_priv *tnt_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (tnt_priv) { - nec_priv = &tnt_priv->nec7210_priv; - if (nec_priv->iobase) - tnt4882_board_reset(tnt_priv, board); - if (tnt_priv->irq) - free_irq(tnt_priv->irq, board); - if (nec_priv->mmiobase) - ioport_unmap(nec_priv->mmiobase); - if (nec_priv->iobase) - release_region(nec_priv->iobase, atgpib_iosize); - if (tnt_priv->pnp_dev) - pnp_device_detach(tnt_priv->pnp_dev); - } - tnt4882_free_private(board); -} - -static int tnt4882_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - return 0; -} - -static struct gpib_interface ni_pci_interface = { - .name = "ni_pci", - .attach = ni_pci_attach, - .detach = ni_pci_detach, - .read = tnt4882_accel_read, - .write = tnt4882_accel_write, - .command = tnt4882_command, - .take_control = tnt4882_take_control, - .go_to_standby = tnt4882_go_to_standby, - .request_system_control = tnt4882_request_system_control, - .interface_clear = tnt4882_interface_clear, - .remote_enable = tnt4882_remote_enable, - .enable_eos = tnt4882_enable_eos, - .disable_eos = tnt4882_disable_eos, - .parallel_poll = tnt4882_parallel_poll, - .parallel_poll_configure = tnt4882_parallel_poll_configure, - .parallel_poll_response = tnt4882_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = tnt4882_line_status, - .update_status = tnt4882_update_status, - .primary_address = tnt4882_primary_address, - .secondary_address = tnt4882_secondary_address, - .serial_poll_response2 = tnt4882_serial_poll_response2, - .serial_poll_status = tnt4882_serial_poll_status, - .t1_delay = tnt4882_t1_delay, - .return_to_local = tnt4882_return_to_local, -}; - -static struct gpib_interface ni_pci_accel_interface = { - .name = "ni_pci_accel", - .attach = ni_pci_attach, - .detach = ni_pci_detach, - .read = tnt4882_accel_read, - .write = tnt4882_accel_write, - .command = tnt4882_command, - .take_control = tnt4882_take_control, - .go_to_standby = tnt4882_go_to_standby, - .request_system_control = tnt4882_request_system_control, - .interface_clear = tnt4882_interface_clear, - .remote_enable = tnt4882_remote_enable, - .enable_eos = tnt4882_enable_eos, - .disable_eos = tnt4882_disable_eos, - .parallel_poll = tnt4882_parallel_poll, - .parallel_poll_configure = tnt4882_parallel_poll_configure, - .parallel_poll_response = tnt4882_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = tnt4882_line_status, - .update_status = tnt4882_update_status, - .primary_address = tnt4882_primary_address, - .secondary_address = tnt4882_secondary_address, - .serial_poll_response2 = tnt4882_serial_poll_response2, - .serial_poll_status = tnt4882_serial_poll_status, - .t1_delay = tnt4882_t1_delay, - .return_to_local = tnt4882_return_to_local, -}; - -static struct gpib_interface ni_isa_interface = { - .name = "ni_isa", - .attach = ni_tnt_isa_attach, - .detach = ni_isa_detach, - .read = tnt4882_accel_read, - .write = tnt4882_accel_write, - .command = tnt4882_command, - .take_control = tnt4882_take_control, - .go_to_standby = tnt4882_go_to_standby, - .request_system_control = tnt4882_request_system_control, - .interface_clear = tnt4882_interface_clear, - .remote_enable = tnt4882_remote_enable, - .enable_eos = tnt4882_enable_eos, - .disable_eos = tnt4882_disable_eos, - .parallel_poll = tnt4882_parallel_poll, - .parallel_poll_configure = tnt4882_parallel_poll_configure, - .parallel_poll_response = tnt4882_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = tnt4882_line_status, - .update_status = tnt4882_update_status, - .primary_address = tnt4882_primary_address, - .secondary_address = tnt4882_secondary_address, - .serial_poll_response2 = tnt4882_serial_poll_response2, - .serial_poll_status = tnt4882_serial_poll_status, - .t1_delay = tnt4882_t1_delay, - .return_to_local = tnt4882_return_to_local, -}; - -static struct gpib_interface ni_nat4882_isa_interface = { - .name = "ni_nat4882_isa", - .attach = ni_nat4882_isa_attach, - .detach = ni_isa_detach, - .read = tnt4882_read, - .write = tnt4882_write, - .command = tnt4882_command_unaccel, - .take_control = tnt4882_take_control, - .go_to_standby = tnt4882_go_to_standby, - .request_system_control = tnt4882_request_system_control, - .interface_clear = tnt4882_interface_clear, - .remote_enable = tnt4882_remote_enable, - .enable_eos = tnt4882_enable_eos, - .disable_eos = tnt4882_disable_eos, - .parallel_poll = tnt4882_parallel_poll, - .parallel_poll_configure = tnt4882_parallel_poll_configure, - .parallel_poll_response = tnt4882_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = tnt4882_line_status, - .update_status = tnt4882_update_status, - .primary_address = tnt4882_primary_address, - .secondary_address = tnt4882_secondary_address, - .serial_poll_response2 = tnt4882_serial_poll_response2, - .serial_poll_status = tnt4882_serial_poll_status, - .t1_delay = tnt4882_t1_delay, - .return_to_local = tnt4882_return_to_local, -}; - -static struct gpib_interface ni_nec_isa_interface = { - .name = "ni_nec_isa", - .attach = ni_nec_isa_attach, - .detach = ni_isa_detach, - .read = tnt4882_read, - .write = tnt4882_write, - .command = tnt4882_command_unaccel, - .take_control = tnt4882_take_control, - .go_to_standby = tnt4882_go_to_standby, - .request_system_control = tnt4882_request_system_control, - .interface_clear = tnt4882_interface_clear, - .remote_enable = tnt4882_remote_enable, - .enable_eos = tnt4882_enable_eos, - .disable_eos = tnt4882_disable_eos, - .parallel_poll = tnt4882_parallel_poll, - .parallel_poll_configure = tnt4882_parallel_poll_configure, - .parallel_poll_response = tnt4882_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = NULL, - .update_status = tnt4882_update_status, - .primary_address = tnt4882_primary_address, - .secondary_address = tnt4882_secondary_address, - .serial_poll_response = tnt4882_serial_poll_response, - .serial_poll_status = tnt4882_serial_poll_status, - .t1_delay = tnt4882_t1_delay, - .return_to_local = tnt4882_return_to_local, -}; - -static struct gpib_interface ni_isa_accel_interface = { - .name = "ni_isa_accel", - .attach = ni_tnt_isa_attach, - .detach = ni_isa_detach, - .read = tnt4882_accel_read, - .write = tnt4882_accel_write, - .command = tnt4882_command, - .take_control = tnt4882_take_control, - .go_to_standby = tnt4882_go_to_standby, - .request_system_control = tnt4882_request_system_control, - .interface_clear = tnt4882_interface_clear, - .remote_enable = tnt4882_remote_enable, - .enable_eos = tnt4882_enable_eos, - .disable_eos = tnt4882_disable_eos, - .parallel_poll = tnt4882_parallel_poll, - .parallel_poll_configure = tnt4882_parallel_poll_configure, - .parallel_poll_response = tnt4882_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = tnt4882_line_status, - .update_status = tnt4882_update_status, - .primary_address = tnt4882_primary_address, - .secondary_address = tnt4882_secondary_address, - .serial_poll_response2 = tnt4882_serial_poll_response2, - .serial_poll_status = tnt4882_serial_poll_status, - .t1_delay = tnt4882_t1_delay, - .return_to_local = tnt4882_return_to_local, -}; - -static struct gpib_interface ni_nat4882_isa_accel_interface = { - .name = "ni_nat4882_isa_accel", - .attach = ni_nat4882_isa_attach, - .detach = ni_isa_detach, - .read = tnt4882_accel_read, - .write = tnt4882_accel_write, - .command = tnt4882_command_unaccel, - .take_control = tnt4882_take_control, - .go_to_standby = tnt4882_go_to_standby, - .request_system_control = tnt4882_request_system_control, - .interface_clear = tnt4882_interface_clear, - .remote_enable = tnt4882_remote_enable, - .enable_eos = tnt4882_enable_eos, - .disable_eos = tnt4882_disable_eos, - .parallel_poll = tnt4882_parallel_poll, - .parallel_poll_configure = tnt4882_parallel_poll_configure, - .parallel_poll_response = tnt4882_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = tnt4882_line_status, - .update_status = tnt4882_update_status, - .primary_address = tnt4882_primary_address, - .secondary_address = tnt4882_secondary_address, - .serial_poll_response2 = tnt4882_serial_poll_response2, - .serial_poll_status = tnt4882_serial_poll_status, - .t1_delay = tnt4882_t1_delay, - .return_to_local = tnt4882_return_to_local, -}; - -static struct gpib_interface ni_nec_isa_accel_interface = { - .name = "ni_nec_isa_accel", - .attach = ni_nec_isa_attach, - .detach = ni_isa_detach, - .read = tnt4882_accel_read, - .write = tnt4882_accel_write, - .command = tnt4882_command_unaccel, - .take_control = tnt4882_take_control, - .go_to_standby = tnt4882_go_to_standby, - .request_system_control = tnt4882_request_system_control, - .interface_clear = tnt4882_interface_clear, - .remote_enable = tnt4882_remote_enable, - .enable_eos = tnt4882_enable_eos, - .disable_eos = tnt4882_disable_eos, - .parallel_poll = tnt4882_parallel_poll, - .parallel_poll_configure = tnt4882_parallel_poll_configure, - .parallel_poll_response = tnt4882_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = NULL, - .update_status = tnt4882_update_status, - .primary_address = tnt4882_primary_address, - .secondary_address = tnt4882_secondary_address, - .serial_poll_response = tnt4882_serial_poll_response, - .serial_poll_status = tnt4882_serial_poll_status, - .t1_delay = tnt4882_t1_delay, - .return_to_local = tnt4882_return_to_local, -}; - -static const struct pci_device_id tnt4882_pci_table[] = { - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB_PLUS)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB_PLUS2)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PXIGPIB)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PMCGPIB)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PCIEGPIB)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PCIE2GPIB)}, - // support for Measurement Computing PCI-488 - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_MC_PCI488)}, - {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_CEC_NI_GPIB)}, - { 0 } -}; -MODULE_DEVICE_TABLE(pci, tnt4882_pci_table); - -static struct pci_driver tnt4882_pci_driver = { - .name = DRV_NAME, - .id_table = tnt4882_pci_table, - .probe = &tnt4882_pci_probe -}; - -#if 0 -/* unused, will be needed when the driver is turned into a pnp_driver */ -static const struct pnp_device_id tnt4882_pnp_table[] = { - {.id = "NICC601"}, - {.id = ""} -}; -MODULE_DEVICE_TABLE(pnp, tnt4882_pnp_table); -#endif - -#ifdef CONFIG_GPIB_PCMCIA -static struct gpib_interface ni_pcmcia_interface; -static struct gpib_interface ni_pcmcia_accel_interface; -static int __init init_ni_gpib_cs(void); -static void __exit exit_ni_gpib_cs(void); -#endif - -static int __init tnt4882_init_module(void) -{ - int result; - - result = pci_register_driver(&tnt4882_pci_driver); - if (result) { - pr_err("pci_register_driver failed: error = %d\n", result); - return result; - } - - result = gpib_register_driver(&ni_isa_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_isa; - } - - result = gpib_register_driver(&ni_isa_accel_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_isa_accel; - } - - result = gpib_register_driver(&ni_nat4882_isa_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_nat4882_isa; - } - - result = gpib_register_driver(&ni_nat4882_isa_accel_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_nat4882_isa_accel; - } - - result = gpib_register_driver(&ni_nec_isa_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_nec_isa; - } - - result = gpib_register_driver(&ni_nec_isa_accel_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_nec_isa_accel; - } - - result = gpib_register_driver(&ni_pci_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_pci; - } - - result = gpib_register_driver(&ni_pci_accel_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_pci_accel; - } - -#ifdef CONFIG_GPIB_PCMCIA - result = gpib_register_driver(&ni_pcmcia_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_pcmcia; - } - - result = gpib_register_driver(&ni_pcmcia_accel_interface, THIS_MODULE); - if (result) { - pr_err("gpib_register_driver failed: error = %d\n", result); - goto err_pcmcia_accel; - } - - result = init_ni_gpib_cs(); - if (result) { - pr_err("pcmcia_register_driver failed: error = %d\n", result); - goto err_pcmcia_driver; - } -#endif - - mite_init(); - - return 0; - -#ifdef CONFIG_GPIB_PCMCIA -err_pcmcia_driver: - gpib_unregister_driver(&ni_pcmcia_accel_interface); -err_pcmcia_accel: - gpib_unregister_driver(&ni_pcmcia_interface); -err_pcmcia: -#endif - gpib_unregister_driver(&ni_pci_accel_interface); -err_pci_accel: - gpib_unregister_driver(&ni_pci_interface); -err_pci: - gpib_unregister_driver(&ni_nec_isa_accel_interface); -err_nec_isa_accel: - gpib_unregister_driver(&ni_nec_isa_interface); -err_nec_isa: - gpib_unregister_driver(&ni_nat4882_isa_accel_interface); -err_nat4882_isa_accel: - gpib_unregister_driver(&ni_nat4882_isa_interface); -err_nat4882_isa: - gpib_unregister_driver(&ni_isa_accel_interface); -err_isa_accel: - gpib_unregister_driver(&ni_isa_interface); -err_isa: - pci_unregister_driver(&tnt4882_pci_driver); - - return result; -} - -static void __exit tnt4882_exit_module(void) -{ - gpib_unregister_driver(&ni_isa_interface); - gpib_unregister_driver(&ni_isa_accel_interface); - gpib_unregister_driver(&ni_nat4882_isa_interface); - gpib_unregister_driver(&ni_nat4882_isa_accel_interface); - gpib_unregister_driver(&ni_nec_isa_interface); - gpib_unregister_driver(&ni_nec_isa_accel_interface); - gpib_unregister_driver(&ni_pci_interface); - gpib_unregister_driver(&ni_pci_accel_interface); -#ifdef CONFIG_GPIB_PCMCIA - gpib_unregister_driver(&ni_pcmcia_interface); - gpib_unregister_driver(&ni_pcmcia_accel_interface); - exit_ni_gpib_cs(); -#endif - - mite_cleanup(); - - pci_unregister_driver(&tnt4882_pci_driver); -} - -#ifdef CONFIG_GPIB_PCMCIA - -#include <linux/kernel.h> -#include <linux/moduleparam.h> -#include <linux/ptrace.h> -#include <linux/timer.h> -#include <linux/io.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/cisreg.h> -#include <pcmcia/ds.h> - -static int ni_gpib_config(struct pcmcia_device *link); -static void ni_gpib_release(struct pcmcia_device *link); -static void ni_pcmcia_detach(struct gpib_board *board); - -/* - * A linked list of "instances" of the dummy device. Each actual - * PCMCIA card corresponds to one device instance, and is described - * by one dev_link_t structure (defined in ds.h). - * - * You may not want to use a linked list for this -- for example, the - * memory card driver uses an array of dev_link_t pointers, where minor - * device numbers are used to derive the corresponding array index. - * - * I think this dev_list is obsolete but the pointer is needed to keep - * the module instance for the ni_pcmcia_attach function. - */ - -static struct pcmcia_device *curr_dev; - -struct local_info_t { - struct pcmcia_device *p_dev; - struct gpib_board *dev; - int stop; - struct bus_operations *bus; -}; - -/* - * ni_gpib_probe() creates an "instance" of the driver, allocating - * local data structures for one device. The device is registered - * with Card Services. - */ - -static int ni_gpib_probe(struct pcmcia_device *link) -{ - struct local_info_t *info; - //struct struct gpib_board *dev; - - /* Allocate space for private device-specific data */ - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - info->p_dev = link; - link->priv = info; - - /* - * General socket configuration defaults can go here. In this - * client, we assume very little, and rely on the CIS for almost - * everything. In most clients, many details (i.e., number, sizes, - * and attributes of IO windows) are fixed by the nature of the - * device, and can be hard-wired here. - */ - link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - - /* Register with Card Services */ - curr_dev = link; - return ni_gpib_config(link); -} - -/* - * This deletes a driver "instance". The device is de-registered - * with Card Services. If it has been released, all local data - * structures are freed. Otherwise, the structures will be freed - * when the device is released. - */ -static void ni_gpib_remove(struct pcmcia_device *link) -{ - struct local_info_t *info = link->priv; - //struct struct gpib_board *dev = info->dev; - - if (info->dev) - ni_pcmcia_detach(info->dev); - ni_gpib_release(link); - - //free_netdev(dev); - kfree(info); -} - -static int ni_gpib_config_iteration(struct pcmcia_device *link, void *priv_data) -{ - int retval; - - retval = pcmcia_request_io(link); - if (retval != 0) - return retval; - - return 0; -} - -/* - * ni_gpib_config() is scheduled to run after a CARD_INSERTION event - * is received, to configure the PCMCIA socket, and to make the - * device available to the system. - */ -static int ni_gpib_config(struct pcmcia_device *link) -{ - //struct local_info_t *info = link->priv; - //struct gpib_board *dev = info->dev; - int last_ret; - - last_ret = pcmcia_loop_config(link, &ni_gpib_config_iteration, NULL); - if (last_ret) { - dev_warn(&link->dev, "no configuration found\n"); - ni_gpib_release(link); - return last_ret; - } - - last_ret = pcmcia_enable_device(link); - if (last_ret) { - ni_gpib_release(link); - return last_ret; - } - return 0; -} /* ni_gpib_config */ - -/* - * After a card is removed, ni_gpib_release() will unregister the - * device, and release the PCMCIA configuration. If the device is - * still open, this will be postponed until it is closed. - */ -static void ni_gpib_release(struct pcmcia_device *link) -{ - pcmcia_disable_device(link); -} /* ni_gpib_release */ - -static int ni_gpib_suspend(struct pcmcia_device *link) -{ - //struct local_info_t *info = link->priv; - //struct struct gpib_board *dev = info->dev; - - if (link->open) - dev_warn(&link->dev, "Device still open\n"); - //netif_device_detach(dev); - - return 0; -} - -static int ni_gpib_resume(struct pcmcia_device *link) -{ - //struct local_info_t *info = link->priv; - //struct struct gpib_board *dev = info->dev; - - /*if (link->open) { - * ni_gpib_probe(dev); / really? - * //netif_device_attach(dev); - *} - */ - return ni_gpib_config(link); -} - -static struct pcmcia_device_id ni_pcmcia_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4882), - PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0c71), // NI PCMCIA-GPIB+ - PCMCIA_DEVICE_NULL -}; - -MODULE_DEVICE_TABLE(pcmcia, ni_pcmcia_ids); - -static struct pcmcia_driver ni_gpib_cs_driver = { - .name = "ni_gpib_cs", - .owner = THIS_MODULE, - .drv = { .name = "ni_gpib_cs", }, - .id_table = ni_pcmcia_ids, - .probe = ni_gpib_probe, - .remove = ni_gpib_remove, - .suspend = ni_gpib_suspend, - .resume = ni_gpib_resume, -}; - -static int __init init_ni_gpib_cs(void) -{ - return pcmcia_register_driver(&ni_gpib_cs_driver); -} - -static void __exit exit_ni_gpib_cs(void) -{ - pcmcia_unregister_driver(&ni_gpib_cs_driver); -} - -static const int pcmcia_gpib_iosize = 32; - -static int ni_pcmcia_attach(struct gpib_board *board, const struct gpib_board_config *config) -{ - struct local_info_t *info; - struct tnt4882_priv *tnt_priv; - struct nec7210_priv *nec_priv; - int isr_flags = IRQF_SHARED; - int retval; - - if (!curr_dev) - return -ENODEV; - - info = curr_dev->priv; - info->dev = board; - - board->status = 0; - - if (tnt4882_allocate_private(board)) - return -ENOMEM; - - tnt_priv = board->private_data; - nec_priv = &tnt_priv->nec7210_priv; - nec_priv->type = TNT4882; - nec_priv->read_byte = nec7210_locking_ioport_read_byte; - nec_priv->write_byte = nec7210_locking_ioport_write_byte; - nec_priv->offset = atgpib_reg_offset; - - if (!request_region(curr_dev->resource[0]->start, resource_size(curr_dev->resource[0]), - DRV_NAME)) - return -ENOMEM; - - nec_priv->mmiobase = ioport_map(curr_dev->resource[0]->start, - resource_size(curr_dev->resource[0])); - if (!nec_priv->mmiobase) - return -ENOMEM; - - // get irq - retval = request_irq(curr_dev->irq, tnt4882_interrupt, isr_flags, DRV_NAME, board); - if (retval) { - dev_err(board->gpib_dev, "failed to obtain PCMCIA irq %d\n", curr_dev->irq); - return retval; - } - tnt_priv->irq = curr_dev->irq; - - tnt4882_init(tnt_priv, board); - - return 0; -} - -static void ni_pcmcia_detach(struct gpib_board *board) -{ - struct tnt4882_priv *tnt_priv = board->private_data; - struct nec7210_priv *nec_priv; - - if (tnt_priv) { - nec_priv = &tnt_priv->nec7210_priv; - if (tnt_priv->irq) - free_irq(tnt_priv->irq, board); - if (nec_priv->mmiobase) - ioport_unmap(nec_priv->mmiobase); - if (nec_priv->iobase) { - tnt4882_board_reset(tnt_priv, board); - release_region(nec_priv->iobase, pcmcia_gpib_iosize); - } - } - tnt4882_free_private(board); -} - -static struct gpib_interface ni_pcmcia_interface = { - .name = "ni_pcmcia", - .attach = ni_pcmcia_attach, - .detach = ni_pcmcia_detach, - .read = tnt4882_accel_read, - .write = tnt4882_accel_write, - .command = tnt4882_command, - .take_control = tnt4882_take_control, - .go_to_standby = tnt4882_go_to_standby, - .request_system_control = tnt4882_request_system_control, - .interface_clear = tnt4882_interface_clear, - .remote_enable = tnt4882_remote_enable, - .enable_eos = tnt4882_enable_eos, - .disable_eos = tnt4882_disable_eos, - .parallel_poll = tnt4882_parallel_poll, - .parallel_poll_configure = tnt4882_parallel_poll_configure, - .parallel_poll_response = tnt4882_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = tnt4882_line_status, - .update_status = tnt4882_update_status, - .primary_address = tnt4882_primary_address, - .secondary_address = tnt4882_secondary_address, - .serial_poll_response = tnt4882_serial_poll_response, - .serial_poll_status = tnt4882_serial_poll_status, - .t1_delay = tnt4882_t1_delay, - .return_to_local = tnt4882_return_to_local, -}; - -static struct gpib_interface ni_pcmcia_accel_interface = { - .name = "ni_pcmcia_accel", - .attach = ni_pcmcia_attach, - .detach = ni_pcmcia_detach, - .read = tnt4882_accel_read, - .write = tnt4882_accel_write, - .command = tnt4882_command, - .take_control = tnt4882_take_control, - .go_to_standby = tnt4882_go_to_standby, - .request_system_control = tnt4882_request_system_control, - .interface_clear = tnt4882_interface_clear, - .remote_enable = tnt4882_remote_enable, - .enable_eos = tnt4882_enable_eos, - .disable_eos = tnt4882_disable_eos, - .parallel_poll = tnt4882_parallel_poll, - .parallel_poll_configure = tnt4882_parallel_poll_configure, - .parallel_poll_response = tnt4882_parallel_poll_response, - .local_parallel_poll_mode = NULL, // XXX - .line_status = tnt4882_line_status, - .update_status = tnt4882_update_status, - .primary_address = tnt4882_primary_address, - .secondary_address = tnt4882_secondary_address, - .serial_poll_response = tnt4882_serial_poll_response, - .serial_poll_status = tnt4882_serial_poll_status, - .t1_delay = tnt4882_t1_delay, - .return_to_local = tnt4882_return_to_local, -}; - -#endif // CONFIG_GPIB_PCMCIA - -module_init(tnt4882_init_module); -module_exit(tnt4882_exit_module); diff --git a/drivers/staging/gpib/uapi/gpib.h b/drivers/staging/gpib/uapi/gpib.h deleted file mode 100644 index ddf82a4d989f..000000000000 --- a/drivers/staging/gpib/uapi/gpib.h +++ /dev/null @@ -1,104 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _GPIB_H -#define _GPIB_H - -#define GPIB_MAX_NUM_BOARDS 16 -#define GPIB_MAX_NUM_DESCRIPTORS 0x1000 - -enum ibsta_bit_numbers { - DCAS_NUM = 0, - DTAS_NUM = 1, - LACS_NUM = 2, - TACS_NUM = 3, - ATN_NUM = 4, - CIC_NUM = 5, - REM_NUM = 6, - LOK_NUM = 7, - CMPL_NUM = 8, - EVENT_NUM = 9, - SPOLL_NUM = 10, - RQS_NUM = 11, - SRQI_NUM = 12, - END_NUM = 13, - TIMO_NUM = 14, - ERR_NUM = 15 -}; - -/* IBSTA status bits (returned by all functions) */ -enum ibsta_bits { - DCAS = (1 << DCAS_NUM), /* device clear state */ - DTAS = (1 << DTAS_NUM), /* device trigger state */ - LACS = (1 << LACS_NUM), /* GPIB interface is addressed as Listener */ - TACS = (1 << TACS_NUM), /* GPIB interface is addressed as Talker */ - ATN = (1 << ATN_NUM), /* Attention is asserted */ - CIC = (1 << CIC_NUM), /* GPIB interface is Controller-in-Charge */ - REM = (1 << REM_NUM), /* remote state */ - LOK = (1 << LOK_NUM), /* lockout state */ - CMPL = (1 << CMPL_NUM), /* I/O is complete */ - EVENT = (1 << EVENT_NUM), /* DCAS, DTAS, or IFC has occurred */ - SPOLL = (1 << SPOLL_NUM), /* board serial polled by busmaster */ - RQS = (1 << RQS_NUM), /* Device requesting service */ - SRQI = (1 << SRQI_NUM), /* SRQ is asserted */ - END = (1 << END_NUM), /* EOI or EOS encountered */ - TIMO = (1 << TIMO_NUM), /* Time limit on I/O or wait function exceeded */ - ERR = (1 << ERR_NUM), /* Function call terminated on error */ - - device_status_mask = ERR | TIMO | END | CMPL | RQS, - board_status_mask = ERR | TIMO | END | CMPL | SPOLL | - EVENT | LOK | REM | CIC | ATN | TACS | LACS | DTAS | DCAS | SRQI, -}; - -/* End-of-string (EOS) modes for use with ibeos */ - -enum eos_flags { - EOS_MASK = 0x1c00, - REOS = 0x0400, /* Terminate reads on EOS */ - XEOS = 0x800, /* assert EOI when EOS char is sent */ - BIN = 0x1000 /* Do 8-bit compare on EOS */ -}; - -/* GPIB Bus Control Lines bit vector */ -enum bus_control_line { - VALID_DAV = 0x01, - VALID_NDAC = 0x02, - VALID_NRFD = 0x04, - VALID_IFC = 0x08, - VALID_REN = 0x10, - VALID_SRQ = 0x20, - VALID_ATN = 0x40, - VALID_EOI = 0x80, - VALID_ALL = 0xff, - BUS_DAV = 0x0100, /* DAV line status bit */ - BUS_NDAC = 0x0200, /* NDAC line status bit */ - BUS_NRFD = 0x0400, /* NRFD line status bit */ - BUS_IFC = 0x0800, /* IFC line status bit */ - BUS_REN = 0x1000, /* REN line status bit */ - BUS_SRQ = 0x2000, /* SRQ line status bit */ - BUS_ATN = 0x4000, /* ATN line status bit */ - BUS_EOI = 0x8000 /* EOI line status bit */ -}; - -enum ppe_bits { - PPC_DISABLE = 0x10, - PPC_SENSE = 0x8, /* parallel poll sense bit */ - PPC_DIO_MASK = 0x7 -}; - -enum { - request_service_bit = 0x40, -}; - -enum gpib_events { - EVENT_NONE = 0, - EVENT_DEV_TRG = 1, - EVENT_DEV_CLR = 2, - EVENT_IFC = 3 -}; - -#endif /* _GPIB_H */ - diff --git a/drivers/staging/gpib/uapi/gpib_ioctl.h b/drivers/staging/gpib/uapi/gpib_ioctl.h deleted file mode 100644 index 55bf5e55507a..000000000000 --- a/drivers/staging/gpib/uapi/gpib_ioctl.h +++ /dev/null @@ -1,167 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/*************************************************************************** - * copyright : (C) 2002 by Frank Mori Hess - ***************************************************************************/ - -#ifndef _GPIB_IOCTL_H -#define _GPIB_IOCTL_H - -#include <asm/ioctl.h> -#include <linux/types.h> - -#define GPIB_CODE 160 - -struct gpib_board_type_ioctl { - char name[100]; -}; - -/* argument for read/write/command ioctls */ -struct gpib_read_write_ioctl { - __u64 buffer_ptr; - __u32 requested_transfer_count; - __u32 completed_transfer_count; - __s32 end; /* end flag return for reads, end io suppression request for cmd*/ - __s32 handle; -}; - -struct gpib_open_dev_ioctl { - __u32 handle; - __u32 pad; - __s32 sad; - __u32 is_board; -}; - -struct gpib_close_dev_ioctl { - __u32 handle; -}; - -struct gpib_serial_poll_ioctl { - __u32 pad; - __s32 sad; - __u8 status_byte; - __u8 padding[3]; // align to 32 bit boundary -}; - -struct gpib_eos_ioctl { - __s32 eos; - __s32 eos_flags; -}; - -struct gpib_wait_ioctl { - __s32 handle; - __s32 wait_mask; - __s32 clear_mask; - __s32 set_mask; - __s32 ibsta; - __s32 pad; - __s32 sad; - __u32 usec_timeout; -}; - -struct gpib_online_ioctl { - __u64 init_data_ptr; - __s32 init_data_length; - __s32 online; -}; - -struct gpib_spoll_bytes_ioctl { - __u32 num_bytes; - __u32 pad; - __s32 sad; -}; - -struct gpib_board_info_ioctl { - __u32 pad; - __s32 sad; - __s32 parallel_poll_configuration; - __s32 autopolling; - __s32 is_system_controller; - __u32 t1_delay; - unsigned ist : 1; - unsigned no_7_bit_eos : 1; - unsigned padding :30; // align to 32 bit boundary -}; - -struct gpib_select_pci_ioctl { - __s32 pci_bus; - __s32 pci_slot; -}; - -struct gpib_ppoll_config_ioctl { - __u8 config; - unsigned set_ist : 1; - unsigned clear_ist : 1; - unsigned padding :22; // align to 32 bit boundary -}; - -struct gpib_pad_ioctl { - __u32 handle; - __u32 pad; -}; - -struct gpib_sad_ioctl { - __u32 handle; - __s32 sad; -}; - -// select a piece of hardware to attach by its sysfs device path -struct gpib_select_device_path_ioctl { - char device_path[0x1000]; -}; - -// update status byte and request service -struct gpib_request_service2 { - __u8 status_byte; - __u8 padding[3]; // align to 32 bit boundary - __s32 new_reason_for_service; -}; - -/* Standard functions. */ -enum gpib_ioctl { - IBRD = _IOWR(GPIB_CODE, 100, struct gpib_read_write_ioctl), - IBWRT = _IOWR(GPIB_CODE, 101, struct gpib_read_write_ioctl), - IBCMD = _IOWR(GPIB_CODE, 102, struct gpib_read_write_ioctl), - IBOPENDEV = _IOWR(GPIB_CODE, 3, struct gpib_open_dev_ioctl), - IBCLOSEDEV = _IOW(GPIB_CODE, 4, struct gpib_close_dev_ioctl), - IBWAIT = _IOWR(GPIB_CODE, 5, struct gpib_wait_ioctl), - IBRPP = _IOWR(GPIB_CODE, 6, __u8), - - IBSIC = _IOW(GPIB_CODE, 9, __u32), - IBSRE = _IOW(GPIB_CODE, 10, __s32), - IBGTS = _IO(GPIB_CODE, 11), - IBCAC = _IOW(GPIB_CODE, 12, __s32), - IBLINES = _IOR(GPIB_CODE, 14, __s16), - IBPAD = _IOW(GPIB_CODE, 15, struct gpib_pad_ioctl), - IBSAD = _IOW(GPIB_CODE, 16, struct gpib_sad_ioctl), - IBTMO = _IOW(GPIB_CODE, 17, __u32), - IBRSP = _IOWR(GPIB_CODE, 18, struct gpib_serial_poll_ioctl), - IBEOS = _IOW(GPIB_CODE, 19, struct gpib_eos_ioctl), - IBRSV = _IOW(GPIB_CODE, 20, __u8), - CFCBASE = _IOW(GPIB_CODE, 21, __u64), - CFCIRQ = _IOW(GPIB_CODE, 22, __u32), - CFCDMA = _IOW(GPIB_CODE, 23, __u32), - CFCBOARDTYPE = _IOW(GPIB_CODE, 24, struct gpib_board_type_ioctl), - - IBMUTEX = _IOW(GPIB_CODE, 26, __s32), - IBSPOLL_BYTES = _IOWR(GPIB_CODE, 27, struct gpib_spoll_bytes_ioctl), - IBPPC = _IOW(GPIB_CODE, 28, struct gpib_ppoll_config_ioctl), - IBBOARD_INFO = _IOR(GPIB_CODE, 29, struct gpib_board_info_ioctl), - - IBQUERY_BOARD_RSV = _IOR(GPIB_CODE, 31, __s32), - IBSELECT_PCI = _IOWR(GPIB_CODE, 32, struct gpib_select_pci_ioctl), - IBEVENT = _IOR(GPIB_CODE, 33, __s16), - IBRSC = _IOW(GPIB_CODE, 34, __s32), - IB_T1_DELAY = _IOW(GPIB_CODE, 35, __u32), - IBLOC = _IO(GPIB_CODE, 36), - - IBAUTOSPOLL = _IOW(GPIB_CODE, 38, __s16), - IBONL = _IOW(GPIB_CODE, 39, struct gpib_online_ioctl), - IBPP2_SET = _IOW(GPIB_CODE, 40, __s16), - IBPP2_GET = _IOR(GPIB_CODE, 41, __s16), - IBSELECT_DEVICE_PATH = _IOW(GPIB_CODE, 43, struct gpib_select_device_path_ioctl), - // 44 was IBSELECT_SERIAL_NUMBER - IBRSV2 = _IOW(GPIB_CODE, 45, struct gpib_request_service2) -}; - -#endif /* _GPIB_IOCTL_H */ diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 2f05e761fb9a..444c53b4e08d 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -807,6 +807,7 @@ int gbaudio_register_module(struct gbaudio_module_info *module) { int ret; struct snd_soc_component *comp; + struct snd_soc_dapm_context *dapm; struct gbaudio_jack *jack = NULL; if (!gbcodec) { @@ -815,6 +816,7 @@ int gbaudio_register_module(struct gbaudio_module_info *module) } comp = gbcodec->component; + dapm = snd_soc_component_to_dapm(comp); mutex_lock(&gbcodec->register_mutex); @@ -833,18 +835,18 @@ int gbaudio_register_module(struct gbaudio_module_info *module) } if (module->dapm_widgets) - snd_soc_dapm_new_controls(&comp->dapm, module->dapm_widgets, + snd_soc_dapm_new_controls(dapm, module->dapm_widgets, module->num_dapm_widgets); if (module->controls) snd_soc_add_component_controls(comp, module->controls, module->num_controls); if (module->dapm_routes) - snd_soc_dapm_add_routes(&comp->dapm, module->dapm_routes, + snd_soc_dapm_add_routes(dapm, module->dapm_routes, module->num_dapm_routes); /* card already instantiated, create widgets here only */ if (comp->card->instantiated) { - gbaudio_dapm_link_component_dai_widgets(comp->card, &comp->dapm); + gbaudio_dapm_link_component_dai_widgets(comp->card, dapm); #ifdef CONFIG_SND_JACK /* * register jack devices for this module @@ -966,9 +968,11 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) #endif if (module->dapm_routes) { + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(comp); + dev_dbg(comp->dev, "Removing %d routes\n", module->num_dapm_routes); - snd_soc_dapm_del_routes(&comp->dapm, module->dapm_routes, + snd_soc_dapm_del_routes(dapm, module->dapm_routes, module->num_dapm_routes); } if (module->controls) { @@ -979,9 +983,11 @@ void gbaudio_unregister_module(struct gbaudio_module_info *module) module->num_controls); } if (module->dapm_widgets) { + struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(comp); + dev_dbg(comp->dev, "Removing %d widgets\n", module->num_dapm_widgets); - gbaudio_dapm_free_controls(&comp->dapm, module->dapm_widgets, + gbaudio_dapm_free_controls(dapm, module->dapm_widgets, module->num_dapm_widgets); } diff --git a/drivers/staging/greybus/audio_helper.c b/drivers/staging/greybus/audio_helper.c index 97ce5b9ad7fd..b4873c6d6bed 100644 --- a/drivers/staging/greybus/audio_helper.c +++ b/drivers/staging/greybus/audio_helper.c @@ -115,12 +115,13 @@ int gbaudio_dapm_free_controls(struct snd_soc_dapm_context *dapm, { int i; struct snd_soc_dapm_widget *w, *tmp_w; + struct snd_soc_card *card = snd_soc_dapm_to_card(dapm); - mutex_lock(&dapm->card->dapm_mutex); + mutex_lock(&card->dapm_mutex); for (i = 0; i < num; i++) { /* below logic can be optimized to identify widget pointer */ w = NULL; - list_for_each_entry(tmp_w, &dapm->card->widgets, list) { + list_for_each_entry(tmp_w, &card->widgets, list) { if (tmp_w->dapm == dapm && !strcmp(tmp_w->name, widget->name)) { w = tmp_w; @@ -128,7 +129,7 @@ int gbaudio_dapm_free_controls(struct snd_soc_dapm_context *dapm, } } if (!w) { - dev_err(dapm->dev, "%s: widget not found\n", + dev_err(card->dev, "%s: widget not found\n", widget->name); widget++; continue; @@ -136,7 +137,7 @@ int gbaudio_dapm_free_controls(struct snd_soc_dapm_context *dapm, widget++; gbaudio_dapm_free_widget(w); } - mutex_unlock(&dapm->card->dapm_mutex); + mutex_unlock(&card->dapm_mutex); return 0; } diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c index 6ca938dca4fd..76146f91cddc 100644 --- a/drivers/staging/greybus/audio_topology.c +++ b/drivers/staging/greybus/audio_topology.c @@ -163,7 +163,7 @@ static int gbcodec_mixer_ctl_info(struct snd_kcontrol *kcontrol, struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_info *info; struct gbaudio_module_info *module; - struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); struct gbaudio_codec_info *gbcodec = snd_soc_component_get_drvdata(comp); dev_dbg(comp->dev, "Entered %s:%s\n", __func__, kcontrol->id.name); @@ -214,7 +214,7 @@ static int gbcodec_mixer_ctl_get(struct snd_kcontrol *kcontrol, struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; struct gbaudio_module_info *module; - struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); struct gbaudio_codec_info *gb = snd_soc_component_get_drvdata(comp); struct gb_bundle *bundle; @@ -276,7 +276,7 @@ static int gbcodec_mixer_ctl_put(struct snd_kcontrol *kcontrol, struct gbaudio_ctl_pvt *data; struct gb_audio_ctl_elem_value gbvalue; struct gbaudio_module_info *module; - struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); struct gbaudio_codec_info *gb = snd_soc_component_get_drvdata(comp); struct gb_bundle *bundle; @@ -380,7 +380,7 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, struct gbaudio_module_info *module; struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct device *codec_dev = widget->dapm->dev; + struct device *codec_dev = snd_soc_dapm_to_dev(widget->dapm); struct gbaudio_codec_info *gb = dev_get_drvdata(codec_dev); struct gb_bundle *bundle; @@ -393,7 +393,7 @@ static int gbcodec_mixer_dapm_ctl_get(struct snd_kcontrol *kcontrol, bundle = to_gb_bundle(module->dev); if (data->vcount == 2) - dev_warn(widget->dapm->dev, + dev_warn(codec_dev, "GB: Control '%s' is stereo, which is not supported\n", kcontrol->id.name); @@ -429,7 +429,7 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, struct gbaudio_module_info *module; struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); struct snd_soc_dapm_widget *widget = wlist->widgets[0]; - struct device *codec_dev = widget->dapm->dev; + struct device *codec_dev = snd_soc_dapm_to_dev(widget->dapm); struct gbaudio_codec_info *gb = dev_get_drvdata(codec_dev); struct gb_bundle *bundle; @@ -443,7 +443,7 @@ static int gbcodec_mixer_dapm_ctl_put(struct snd_kcontrol *kcontrol, bundle = to_gb_bundle(module->dev); if (data->vcount == 2) - dev_warn(widget->dapm->dev, + dev_warn(codec_dev, "GB: Control '%s' is stereo, which is not supported\n", kcontrol->id.name); @@ -543,7 +543,7 @@ static int gbcodec_enum_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int ret, ctl_id; - struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); struct gbaudio_codec_info *gb = snd_soc_component_get_drvdata(comp); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct gb_audio_ctl_elem_value gbvalue; @@ -588,7 +588,7 @@ static int gbcodec_enum_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int ret, ctl_id; - struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); struct gbaudio_codec_info *gb = snd_soc_component_get_drvdata(comp); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct gb_audio_ctl_elem_value gbvalue; @@ -712,7 +712,7 @@ static int gbcodec_enum_dapm_ctl_get(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct gbaudio_module_info *module; struct gb_audio_ctl_elem_value gbvalue; - struct device *codec_dev = widget->dapm->dev; + struct device *codec_dev = snd_soc_dapm_to_dev(widget->dapm); struct gbaudio_codec_info *gb = dev_get_drvdata(codec_dev); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct gb_bundle *bundle; @@ -759,7 +759,7 @@ static int gbcodec_enum_dapm_ctl_put(struct snd_kcontrol *kcontrol, struct snd_soc_dapm_widget *widget = wlist->widgets[0]; struct gb_audio_ctl_elem_value gbvalue; struct gbaudio_module_info *module; - struct device *codec_dev = widget->dapm->dev; + struct device *codec_dev = snd_soc_dapm_to_dev(widget->dapm); struct gbaudio_codec_info *gb = dev_get_drvdata(codec_dev); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; struct gb_bundle *bundle; @@ -924,7 +924,7 @@ static int gbaudio_widget_event(struct snd_soc_dapm_widget *w, { int wid; int ret; - struct device *codec_dev = w->dapm->dev; + struct device *codec_dev = snd_soc_dapm_to_dev(w->dapm); struct gbaudio_codec_info *gbcodec = dev_get_drvdata(codec_dev); struct gbaudio_module_info *module; struct gb_bundle *bundle; diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c index 10df5c37c83e..5cece0a6606f 100644 --- a/drivers/staging/greybus/uart.c +++ b/drivers/staging/greybus/uart.c @@ -879,14 +879,18 @@ static int gb_uart_probe(struct gbphy_device *gbphy_dev, if (retval) goto exit_put_port; - send_control(gb_tty, gb_tty->ctrlout); + retval = send_control(gb_tty, gb_tty->ctrlout); + if (retval) + goto exit_connection_disable; /* initialize the uart to be 9600n81 */ gb_tty->line_coding.rate = cpu_to_le32(9600); gb_tty->line_coding.format = GB_SERIAL_1_STOP_BITS; gb_tty->line_coding.parity = GB_SERIAL_NO_PARITY; gb_tty->line_coding.data_bits = 8; - send_line_coding(gb_tty); + retval = send_line_coding(gb_tty); + if (retval) + goto exit_connection_disable; retval = gb_connection_enable(connection); if (retval) diff --git a/drivers/staging/iio/addac/adt7316.c b/drivers/staging/iio/addac/adt7316.c index 16f30c4f1aa0..8a9a8262c2be 100644 --- a/drivers/staging/iio/addac/adt7316.c +++ b/drivers/staging/iio/addac/adt7316.c @@ -216,7 +216,7 @@ static ssize_t adt7316_show_enabled(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_EN)); + return sysfs_emit(buf, "%d\n", !!(chip->config1 & ADT7316_EN)); } static ssize_t _adt7316_store_enabled(struct adt7316_chip_info *chip, @@ -274,7 +274,7 @@ static ssize_t adt7316_show_select_ex_temp(struct device *dev, if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX) return -EPERM; - return sprintf(buf, "%d\n", !!(chip->config1 & ADT7516_SEL_EX_TEMP)); + return sysfs_emit(buf, "%d\n", !!(chip->config1 & ADT7516_SEL_EX_TEMP)); } static ssize_t adt7316_store_select_ex_temp(struct device *dev, @@ -316,9 +316,9 @@ static ssize_t adt7316_show_mode(struct device *dev, struct adt7316_chip_info *chip = iio_priv(dev_info); if (chip->config2 & ADT7316_AD_SINGLE_CH_MODE) - return sprintf(buf, "single_channel\n"); + return sysfs_emit(buf, "single_channel\n"); - return sprintf(buf, "round_robin\n"); + return sysfs_emit(buf, "round_robin\n"); } static ssize_t adt7316_store_mode(struct device *dev, @@ -353,7 +353,7 @@ static ssize_t adt7316_show_all_modes(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "single_channel\nround_robin\n"); + return sysfs_emit(buf, "single_channel\nround_robin\n"); } static IIO_DEVICE_ATTR(all_modes, 0444, adt7316_show_all_modes, NULL, 0); @@ -370,29 +370,29 @@ static ssize_t adt7316_show_ad_channel(struct device *dev, switch (chip->config2 & ADT7516_AD_SINGLE_CH_MASK) { case ADT7316_AD_SINGLE_CH_VDD: - return sprintf(buf, "0 - VDD\n"); + return sysfs_emit(buf, "0 - VDD\n"); case ADT7316_AD_SINGLE_CH_IN: - return sprintf(buf, "1 - Internal Temperature\n"); + return sysfs_emit(buf, "1 - Internal Temperature\n"); case ADT7316_AD_SINGLE_CH_EX: if (((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) && (chip->config1 & ADT7516_SEL_AIN1_2_EX_TEMP_MASK) == 0) - return sprintf(buf, "2 - AIN1\n"); + return sysfs_emit(buf, "2 - AIN1\n"); - return sprintf(buf, "2 - External Temperature\n"); + return sysfs_emit(buf, "2 - External Temperature\n"); case ADT7516_AD_SINGLE_CH_AIN2: if ((chip->config1 & ADT7516_SEL_AIN1_2_EX_TEMP_MASK) == 0) - return sprintf(buf, "3 - AIN2\n"); + return sysfs_emit(buf, "3 - AIN2\n"); - return sprintf(buf, "N/A\n"); + return sysfs_emit(buf, "N/A\n"); case ADT7516_AD_SINGLE_CH_AIN3: if (chip->config1 & ADT7516_SEL_AIN3) - return sprintf(buf, "4 - AIN3\n"); + return sysfs_emit(buf, "4 - AIN3\n"); - return sprintf(buf, "N/A\n"); + return sysfs_emit(buf, "N/A\n"); case ADT7516_AD_SINGLE_CH_AIN4: - return sprintf(buf, "5 - AIN4\n"); + return sysfs_emit(buf, "5 - AIN4\n"); default: - return sprintf(buf, "N/A\n"); + return sysfs_emit(buf, "N/A\n"); } } @@ -453,10 +453,10 @@ static ssize_t adt7316_show_all_ad_channels(struct device *dev, return -EPERM; if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) - return sprintf(buf, "0 - VDD\n1 - Internal Temperature\n" + return sysfs_emit(buf, "0 - VDD\n1 - Internal Temperature\n" "2 - External Temperature or AIN1\n" "3 - AIN2\n4 - AIN3\n5 - AIN4\n"); - return sprintf(buf, "0 - VDD\n1 - Internal Temperature\n" + return sysfs_emit(buf, "0 - VDD\n1 - Internal Temperature\n" "2 - External Temperature\n"); } @@ -470,7 +470,7 @@ static ssize_t adt7316_show_disable_averaging(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return sprintf(buf, "%d\n", + return sysfs_emit(buf, "%d\n", !!(chip->config2 & ADT7316_DISABLE_AVERAGING)); } @@ -509,7 +509,7 @@ static ssize_t adt7316_show_enable_smbus_timeout(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return sprintf(buf, "%d\n", + return sysfs_emit(buf, "%d\n", !!(chip->config2 & ADT7316_EN_SMBUS_TIMEOUT)); } @@ -548,7 +548,7 @@ static ssize_t adt7316_show_powerdown(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_PD)); + return sysfs_emit(buf, "%d\n", !!(chip->config1 & ADT7316_PD)); } static ssize_t adt7316_store_powerdown(struct device *dev, @@ -586,7 +586,7 @@ static ssize_t adt7316_show_fast_ad_clock(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return sprintf(buf, "%d\n", !!(chip->config3 & ADT7316_ADCLK_22_5)); + return sysfs_emit(buf, "%d\n", !!(chip->config3 & ADT7316_ADCLK_22_5)); } static ssize_t adt7316_store_fast_ad_clock(struct device *dev, @@ -626,10 +626,10 @@ static ssize_t adt7316_show_da_high_resolution(struct device *dev, if (chip->config3 & ADT7316_DA_HIGH_RESOLUTION) { if (chip->id != ID_ADT7318 && chip->id != ID_ADT7519) - return sprintf(buf, "1 (10 bits)\n"); + return sysfs_emit(buf, "1 (10 bits)\n"); } - return sprintf(buf, "0 (8 bits)\n"); + return sysfs_emit(buf, "0 (8 bits)\n"); } static ssize_t adt7316_store_da_high_resolution(struct device *dev, @@ -673,7 +673,7 @@ static ssize_t adt7316_show_AIN_internal_Vref(struct device *dev, if ((chip->id & ID_FAMILY_MASK) != ID_ADT75XX) return -EPERM; - return sprintf(buf, "%d\n", + return sysfs_emit(buf, "%d\n", !!(chip->config3 & ADT7516_AIN_IN_VREF)); } @@ -716,7 +716,7 @@ static ssize_t adt7316_show_enable_prop_DACA(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return sprintf(buf, "%d\n", + return sysfs_emit(buf, "%d\n", !!(chip->config3 & ADT7316_EN_IN_TEMP_PROP_DACA)); } @@ -755,7 +755,7 @@ static ssize_t adt7316_show_enable_prop_DACB(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return sprintf(buf, "%d\n", + return sysfs_emit(buf, "%d\n", !!(chip->config3 & ADT7316_EN_EX_TEMP_PROP_DACB)); } @@ -794,7 +794,7 @@ static ssize_t adt7316_show_DAC_2Vref_ch_mask(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return sprintf(buf, "0x%x\n", + return sysfs_emit(buf, "0x%x\n", chip->dac_config & ADT7316_DA_2VREF_CH_MASK); } @@ -838,20 +838,20 @@ static ssize_t adt7316_show_DAC_update_mode(struct device *dev, struct adt7316_chip_info *chip = iio_priv(dev_info); if (!(chip->config3 & ADT7316_DA_EN_VIA_DAC_LDAC)) - return sprintf(buf, "manual\n"); + return sysfs_emit(buf, "manual\n"); switch (chip->dac_config & ADT7316_DA_EN_MODE_MASK) { case ADT7316_DA_EN_MODE_SINGLE: - return sprintf(buf, + return sysfs_emit(buf, "0 - auto at any MSB DAC writing\n"); case ADT7316_DA_EN_MODE_AB_CD: - return sprintf(buf, + return sysfs_emit(buf, "1 - auto at MSB DAC AB and CD writing\n"); case ADT7316_DA_EN_MODE_ABCD: - return sprintf(buf, + return sysfs_emit(buf, "2 - auto at MSB DAC ABCD writing\n"); default: /* ADT7316_DA_EN_MODE_LDAC */ - return sprintf(buf, "3 - manual\n"); + return sysfs_emit(buf, "3 - manual\n"); } } @@ -898,11 +898,11 @@ static ssize_t adt7316_show_all_DAC_update_modes(struct device *dev, struct adt7316_chip_info *chip = iio_priv(dev_info); if (chip->config3 & ADT7316_DA_EN_VIA_DAC_LDAC) - return sprintf(buf, "0 - auto at any MSB DAC writing\n" + return sysfs_emit(buf, "0 - auto at any MSB DAC writing\n" "1 - auto at MSB DAC AB and CD writing\n" "2 - auto at MSB DAC ABCD writing\n" "3 - manual\n"); - return sprintf(buf, "manual\n"); + return sysfs_emit(buf, "manual\n"); } static IIO_DEVICE_ATTR(all_DAC_update_modes, 0444, @@ -955,7 +955,7 @@ static ssize_t adt7316_show_DA_AB_Vref_bypass(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return sprintf(buf, "%d\n", + return sysfs_emit(buf, "%d\n", !!(chip->dac_config & ADT7316_VREF_BYPASS_DAC_AB)); } @@ -994,7 +994,7 @@ static ssize_t adt7316_show_DA_CD_Vref_bypass(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return sprintf(buf, "%d\n", + return sysfs_emit(buf, "%d\n", !!(chip->dac_config & ADT7316_VREF_BYPASS_DAC_CD)); } @@ -1034,10 +1034,10 @@ static ssize_t adt7316_show_DAC_internal_Vref(struct device *dev, struct adt7316_chip_info *chip = iio_priv(dev_info); if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) - return sprintf(buf, "0x%x\n", + return sysfs_emit(buf, "0x%x\n", (chip->ldac_config & ADT7516_DAC_IN_VREF_MASK) >> ADT7516_DAC_IN_VREF_OFFSET); - return sprintf(buf, "%d\n", + return sysfs_emit(buf, "%d\n", !!(chip->ldac_config & ADT7316_DAC_IN_VREF)); } @@ -1128,7 +1128,7 @@ static ssize_t adt7316_show_ad(struct adt7316_chip_info *chip, data = msb << ADT7316_T_VALUE_FLOAT_OFFSET; data |= (lsb & ADT7316_LSB_VDD_MASK) >> ADT7316_LSB_VDD_OFFSET; - return sprintf(buf, "%d\n", data); + return sysfs_emit(buf, "%d\n", data); default: /* ex_temp and ain */ ret = chip->bus.read(chip->bus.client, ADT7316_LSB_EX_TEMP_AIN, &lsb); @@ -1146,7 +1146,7 @@ static ssize_t adt7316_show_ad(struct adt7316_chip_info *chip, (ADT7316_MSB_EX_TEMP - ADT7316_AD_MSB_DATA_BASE)))); if ((chip->id & ID_FAMILY_MASK) == ID_ADT75XX) - return sprintf(buf, "%d\n", data); + return sysfs_emit(buf, "%d\n", data); break; } @@ -1157,7 +1157,7 @@ static ssize_t adt7316_show_ad(struct adt7316_chip_info *chip, sign = '-'; } - return sprintf(buf, "%c%d.%.2d\n", sign, + return sysfs_emit(buf, "%c%d.%.2d\n", sign, (data >> ADT7316_T_VALUE_FLOAT_OFFSET), (data & ADT7316_T_VALUE_FLOAT_MASK) * 25); } @@ -1247,7 +1247,7 @@ static ssize_t adt7316_show_temp_offset(struct adt7316_chip_info *chip, if (val & 0x80) data -= 256; - return sprintf(buf, "%d\n", data); + return sysfs_emit(buf, "%d\n", data); } static ssize_t adt7316_store_temp_offset(struct adt7316_chip_info *chip, @@ -1415,7 +1415,7 @@ static ssize_t adt7316_show_DAC(struct adt7316_chip_info *chip, data = lsb >> ADT7316_DA_10_BIT_LSB_SHIFT; data |= msb << offset; - return sprintf(buf, "%d\n", data); + return sysfs_emit(buf, "%d\n", data); } static ssize_t adt7316_store_DAC(struct adt7316_chip_info *chip, @@ -1568,7 +1568,7 @@ static ssize_t adt7316_show_device_id(struct device *dev, if (ret) return -EIO; - return sprintf(buf, "%d\n", id); + return sysfs_emit(buf, "%d\n", id); } static IIO_DEVICE_ATTR(device_id, 0444, adt7316_show_device_id, NULL, 0); @@ -1586,7 +1586,7 @@ static ssize_t adt7316_show_manufactorer_id(struct device *dev, if (ret) return -EIO; - return sprintf(buf, "%d\n", id); + return sysfs_emit(buf, "%d\n", id); } static IIO_DEVICE_ATTR(manufactorer_id, 0444, @@ -1605,7 +1605,7 @@ static ssize_t adt7316_show_device_rev(struct device *dev, if (ret) return -EIO; - return sprintf(buf, "%d\n", rev); + return sysfs_emit(buf, "%d\n", rev); } static IIO_DEVICE_ATTR(device_rev, 0444, adt7316_show_device_rev, NULL, 0); @@ -1624,9 +1624,9 @@ static ssize_t adt7316_show_bus_type(struct device *dev, return -EIO; if (stat) - return sprintf(buf, "spi\n"); + return sysfs_emit(buf, "spi\n"); - return sprintf(buf, "i2c\n"); + return sysfs_emit(buf, "i2c\n"); } static IIO_DEVICE_ATTR(bus_type, 0444, adt7316_show_bus_type, NULL, 0); @@ -1836,7 +1836,7 @@ static ssize_t adt7316_show_int_mask(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return sprintf(buf, "0x%x\n", chip->int_mask); + return sysfs_emit(buf, "0x%x\n", chip->int_mask); } /* @@ -1910,7 +1910,7 @@ static inline ssize_t adt7316_show_ad_bound(struct device *dev, data -= 256; } - return sprintf(buf, "%d\n", data); + return sysfs_emit(buf, "%d\n", data); } static inline ssize_t adt7316_set_ad_bound(struct device *dev, @@ -1961,7 +1961,7 @@ static ssize_t adt7316_show_int_enabled(struct device *dev, struct iio_dev *dev_info = dev_to_iio_dev(dev); struct adt7316_chip_info *chip = iio_priv(dev_info); - return sprintf(buf, "%d\n", !!(chip->config1 & ADT7316_INT_EN)); + return sysfs_emit(buf, "%d\n", !!(chip->config1 & ADT7316_INT_EN)); } static ssize_t adt7316_set_int_enabled(struct device *dev, diff --git a/drivers/staging/iio/frequency/ad9834.c b/drivers/staging/iio/frequency/ad9834.c index 0038eb234d40..d339d5e8e043 100644 --- a/drivers/staging/iio/frequency/ad9834.c +++ b/drivers/staging/iio/frequency/ad9834.c @@ -21,9 +21,8 @@ #include <linux/iio/iio.h> #include <linux/iio/sysfs.h> -#include "dds.h" -#include "ad9834.h" +#include "dds.h" /* Registers */ diff --git a/drivers/staging/iio/frequency/ad9834.h b/drivers/staging/iio/frequency/ad9834.h deleted file mode 100644 index 521943aa0e61..000000000000 --- a/drivers/staging/iio/frequency/ad9834.h +++ /dev/null @@ -1,10 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * AD9833/AD9834/AD9837/AD9838 SPI DDS driver - * - * Copyright 2010-2011 Analog Devices Inc. - */ -#ifndef IIO_DDS_AD9834_H_ -#define IIO_DDS_AD9834_H_ - -#endif /* IIO_DDS_AD9834_H_ */ diff --git a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c index 6fc39ab95e46..6050637a0def 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-gc2235.c @@ -491,7 +491,7 @@ static int gc2235_s_power(struct v4l2_subdev *sd, int on) return ret; } -static int startup(struct v4l2_subdev *sd) +static int gc2235_startup(struct v4l2_subdev *sd) { struct gc2235_device *dev = to_gc2235_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -556,7 +556,7 @@ static int gc2235_set_fmt(struct v4l2_subdev *sd, return 0; } - ret = startup(sd); + ret = gc2235_startup(sd); if (ret) { dev_err(&client->dev, "gc2235 startup err\n"); goto err; diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c index c7de7800799a..a4519babf37d 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2722.c @@ -600,7 +600,7 @@ static int ov2722_s_power(struct v4l2_subdev *sd, int on) } /* TODO: remove it. */ -static int startup(struct v4l2_subdev *sd) +static int ov2722_startup(struct v4l2_subdev *sd) { struct ov2722_device *dev = to_ov2722_sensor(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); @@ -662,7 +662,7 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd, dev->pixels_per_line = dev->res->pixels_per_line; dev->lines_per_frame = dev->res->lines_per_frame; - ret = startup(sd); + ret = ov2722_startup(sd); if (ret) { int i = 0; @@ -677,7 +677,7 @@ static int ov2722_set_fmt(struct v4l2_subdev *sd, dev_err(&client->dev, "power up failed, continue\n"); continue; } - ret = startup(sd); + ret = ov2722_startup(sd); if (ret) { dev_err(&client->dev, " startup FAILED!\n"); } else { diff --git a/drivers/staging/media/av7110/av7110.c b/drivers/staging/media/av7110/av7110.c index bc9a2a40afcb..602342d1174f 100644 --- a/drivers/staging/media/av7110/av7110.c +++ b/drivers/staging/media/av7110/av7110.c @@ -321,7 +321,7 @@ static inline void print_time(char *s) struct timespec64 ts; ktime_get_real_ts64(&ts); - pr_info("%s(): %lld.%09ld\n", s, (s64)ts.tv_sec, ts.tv_nsec); + pr_info("%s(): %ptSp\n", s, &ts); #endif } diff --git a/drivers/staging/media/av7110/av7110_ca.c b/drivers/staging/media/av7110/av7110_ca.c index fce4023c9dea..63d9c97a5190 100644 --- a/drivers/staging/media/av7110/av7110_ca.c +++ b/drivers/staging/media/av7110/av7110_ca.c @@ -26,7 +26,7 @@ void CI_handle(struct av7110 *av7110, u8 *data, u16 len) { - unsigned slot_num; + unsigned int slot_num; dprintk(8, "av7110:%p\n", av7110); diff --git a/drivers/staging/media/av7110/av7110_v4l.c b/drivers/staging/media/av7110/av7110_v4l.c index 04e659243f02..200a7a29ea31 100644 --- a/drivers/staging/media/av7110/av7110_v4l.c +++ b/drivers/staging/media/av7110/av7110_v4l.c @@ -940,7 +940,7 @@ static struct saa7146_ext_vv av7110_vv_data_st = { .num_stds = ARRAY_SIZE(standard), .std_callback = &std_callback, - .vbi_fops.write = av7110_vbi_write, + .vbi_write = av7110_vbi_write, }; static struct saa7146_ext_vv av7110_vv_data_c = { @@ -953,6 +953,6 @@ static struct saa7146_ext_vv av7110_vv_data_c = { .num_stds = ARRAY_SIZE(standard), .std_callback = &std_callback, - .vbi_fops.write = av7110_vbi_write, + .vbi_write = av7110_vbi_write, }; diff --git a/drivers/staging/media/imx/imx-media-csc-scaler.c b/drivers/staging/media/imx/imx-media-csc-scaler.c index 1869c5792ecb..0a27330f9790 100644 --- a/drivers/staging/media/imx/imx-media-csc-scaler.c +++ b/drivers/staging/media/imx/imx-media-csc-scaler.c @@ -99,7 +99,7 @@ static void ipu_ic_pp_complete(struct ipu_image_convert_run *run, void *_ctx) src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx); dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); - v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, true); + v4l2_m2m_buf_copy_metadata(src_buf, dst_buf); src_buf->sequence = ctx->sequence++; dst_buf->sequence = src_buf->sequence; diff --git a/drivers/staging/media/ipu3/ipu3.c b/drivers/staging/media/ipu3/ipu3.c index e22a9c092195..bdf5a457752b 100644 --- a/drivers/staging/media/ipu3/ipu3.c +++ b/drivers/staging/media/ipu3/ipu3.c @@ -530,8 +530,7 @@ static irqreturn_t imgu_isr_threaded(int irq, void *imgu_ptr) if (IS_ERR(b)) { if (PTR_ERR(b) != -EBUSY) /* All done */ dev_err(&imgu->pci_dev->dev, - "failed to dequeue buffers (%ld)\n", - PTR_ERR(b)); + "failed to dequeue buffers (%pe)\n", b); break; } diff --git a/drivers/staging/media/ipu3/ipu3.h b/drivers/staging/media/ipu3/ipu3.h index d2ad0a95c5aa..7b2a1eee2c7f 100644 --- a/drivers/staging/media/ipu3/ipu3.h +++ b/drivers/staging/media/ipu3/ipu3.h @@ -127,7 +127,6 @@ struct imgu_device { /* Private fields */ struct v4l2_device v4l2_dev; struct media_device media_dev; - struct v4l2_file_operations v4l2_file_ops; /* MMU driver for css */ struct imgu_mmu_info *mmu; diff --git a/drivers/staging/media/ipu7/ipu7-isys-csi-phy.c b/drivers/staging/media/ipu7/ipu7-isys-csi-phy.c index b8c5db7ae300..2d5717883518 100644 --- a/drivers/staging/media/ipu7/ipu7-isys-csi-phy.c +++ b/drivers/staging/media/ipu7/ipu7-isys-csi-phy.c @@ -307,8 +307,8 @@ static int ipu7_isys_csi_ctrl_dids_config(struct ipu7_isys_csi2 *csi2, u32 id) pad = media_entity_remote_source_pad_unique(&csi2->asd.sd.entity); if (IS_ERR(pad)) { - dev_warn(dev, "can't get remote source pad of %s (%ld)\n", - csi2->asd.sd.name, PTR_ERR(pad)); + dev_warn(dev, "can't get remote source pad of %s (%pe)\n", + csi2->asd.sd.name, pad); return PTR_ERR(pad); } diff --git a/drivers/staging/media/ipu7/ipu7-isys-csi2.c b/drivers/staging/media/ipu7/ipu7-isys-csi2.c index 4023db4a6466..f34eabfe8a98 100644 --- a/drivers/staging/media/ipu7/ipu7-isys-csi2.c +++ b/drivers/staging/media/ipu7/ipu7-isys-csi2.c @@ -55,8 +55,8 @@ s64 ipu7_isys_csi2_get_link_freq(struct ipu7_isys_csi2 *csi2) src_pad = media_entity_remote_source_pad_unique(&csi2->asd.sd.entity); if (IS_ERR(src_pad)) { dev_err(&csi2->isys->adev->auxdev.dev, - "can't get source pad of %s (%ld)\n", - csi2->asd.sd.name, PTR_ERR(src_pad)); + "can't get source pad of %s (%pe)\n", + csi2->asd.sd.name, src_pad); return PTR_ERR(src_pad); } diff --git a/drivers/staging/media/ipu7/ipu7-isys-video.c b/drivers/staging/media/ipu7/ipu7-isys-video.c index 1a7c8a91fffb..8c6730833f24 100644 --- a/drivers/staging/media/ipu7/ipu7-isys-video.c +++ b/drivers/staging/media/ipu7/ipu7-isys-video.c @@ -88,11 +88,6 @@ const struct ipu7_isys_pixelformat ipu7_isys_pfmts[] = { IPU_INSYS_FRAME_FORMAT_RGBA888}, }; -static int video_open(struct file *file) -{ - return v4l2_fh_open(file); -} - const struct ipu7_isys_pixelformat *ipu7_isys_get_isys_format(u32 pixelformat) { unsigned int i; @@ -867,7 +862,7 @@ static const struct v4l2_file_operations isys_fops = { .poll = vb2_fop_poll, .unlocked_ioctl = video_ioctl2, .mmap = vb2_fop_mmap, - .open = video_open, + .open = v4l2_fh_open, .release = vb2_fop_release, }; diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c index fbbf9e6f0f50..9f8b0555b7dc 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c @@ -90,7 +90,7 @@ void cedrus_device_run(void *priv) break; } - v4l2_m2m_buf_copy_metadata(run.src, run.dst, true); + v4l2_m2m_buf_copy_metadata(run.src, run.dst); cedrus_dst_format_set(dev, &ctx->dst_fmt); diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c index 1473f1b1f203..aa9ff7fec4f9 100644 --- a/drivers/staging/media/tegra-video/tegra20.c +++ b/drivers/staging/media/tegra-video/tegra20.c @@ -255,7 +255,7 @@ static int tegra20_channel_host1x_syncpt_init(struct tegra_vi_channel *chan) out_sp = host1x_syncpt_request(&vi->client, HOST1X_SYNCPT_CLIENT_MANAGED); if (!out_sp) - return dev_err_probe(vi->dev, -ENOMEM, "failed to request syncpoint\n"); + return -ENOMEM; chan->mw_ack_sp[0] = out_sp; diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig index 6f420cbcdcff..e89658df6f12 100644 --- a/drivers/staging/most/Kconfig +++ b/drivers/staging/most/Kconfig @@ -24,6 +24,4 @@ source "drivers/staging/most/video/Kconfig" source "drivers/staging/most/dim2/Kconfig" -source "drivers/staging/most/i2c/Kconfig" - endif diff --git a/drivers/staging/most/Makefile b/drivers/staging/most/Makefile index 8b3fc5a7af51..e45084df7803 100644 --- a/drivers/staging/most/Makefile +++ b/drivers/staging/most/Makefile @@ -3,4 +3,3 @@ obj-$(CONFIG_MOST_NET) += net/ obj-$(CONFIG_MOST_VIDEO) += video/ obj-$(CONFIG_MOST_DIM2) += dim2/ -obj-$(CONFIG_MOST_I2C) += i2c/ diff --git a/drivers/staging/most/i2c/Kconfig b/drivers/staging/most/i2c/Kconfig deleted file mode 100644 index ff64283cbad1..000000000000 --- a/drivers/staging/most/i2c/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# MOST I2C configuration -# - -config MOST_I2C - tristate "I2C" - depends on I2C - help - Say Y here if you want to connect via I2C to network transceiver. - - To compile this driver as a module, choose M here: the - module will be called most_i2c. diff --git a/drivers/staging/most/i2c/Makefile b/drivers/staging/most/i2c/Makefile deleted file mode 100644 index 71099dd0f85b..000000000000 --- a/drivers/staging/most/i2c/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_MOST_I2C) += most_i2c.o - -most_i2c-objs := i2c.o diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c deleted file mode 100644 index 184b2dd11fc3..000000000000 --- a/drivers/staging/most/i2c/i2c.c +++ /dev/null @@ -1,374 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * i2c.c - Hardware Dependent Module for I2C Interface - * - * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/err.h> -#include <linux/most.h> - -enum { CH_RX, CH_TX, NUM_CHANNELS }; - -#define MAX_BUFFERS_CONTROL 32 -#define MAX_BUF_SIZE_CONTROL 256 - -/** - * list_first_mbo - get the first mbo from a list - * @ptr: the list head to take the mbo from. - */ -#define list_first_mbo(ptr) \ - list_first_entry(ptr, struct mbo, list) - -static unsigned int polling_rate; -module_param(polling_rate, uint, 0644); -MODULE_PARM_DESC(polling_rate, "Polling rate [Hz]. Default = 0 (use IRQ)"); - -struct hdm_i2c { - struct most_interface most_iface; - struct most_channel_capability capabilities[NUM_CHANNELS]; - struct i2c_client *client; - struct rx { - struct delayed_work dwork; - struct list_head list; - bool int_disabled; - unsigned int delay; - } rx; - char name[64]; -}; - -static inline struct hdm_i2c *to_hdm(struct most_interface *iface) -{ - return container_of(iface, struct hdm_i2c, most_iface); -} - -static irqreturn_t most_irq_handler(int, void *); -static void pending_rx_work(struct work_struct *); - -/** - * configure_channel - called from MOST core to configure a channel - * @most_iface: interface the channel belongs to - * @ch_idx: channel to be configured - * @channel_config: structure that holds the configuration information - * - * Return 0 on success, negative on failure. - * - * Receives configuration information from MOST core and initialize the - * corresponding channel. - */ -static int configure_channel(struct most_interface *most_iface, - int ch_idx, - struct most_channel_config *channel_config) -{ - int ret; - struct hdm_i2c *dev = to_hdm(most_iface); - unsigned int delay, pr; - - BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS); - - if (channel_config->data_type != MOST_CH_CONTROL) { - pr_err("bad data type for channel %d\n", ch_idx); - return -EPERM; - } - - if (channel_config->direction != dev->capabilities[ch_idx].direction) { - pr_err("bad direction for channel %d\n", ch_idx); - return -EPERM; - } - - if (channel_config->direction == MOST_CH_RX) { - if (!polling_rate) { - if (dev->client->irq <= 0) { - pr_err("bad irq: %d\n", dev->client->irq); - return -ENOENT; - } - dev->rx.int_disabled = false; - ret = request_irq(dev->client->irq, most_irq_handler, 0, - dev->client->name, dev); - if (ret) { - pr_err("request_irq(%d) failed: %d\n", - dev->client->irq, ret); - return ret; - } - } else { - delay = msecs_to_jiffies(MSEC_PER_SEC / polling_rate); - dev->rx.delay = delay ? delay : 1; - pr = MSEC_PER_SEC / jiffies_to_msecs(dev->rx.delay); - pr_info("polling rate is %u Hz\n", pr); - } - } - - return 0; -} - -/** - * enqueue - called from MOST core to enqueue a buffer for data transfer - * @most_iface: intended interface - * @ch_idx: ID of the channel the buffer is intended for - * @mbo: pointer to the buffer object - * - * Return 0 on success, negative on failure. - * - * Transmit the data over I2C if it is a "write" request or push the buffer into - * list if it is an "read" request - */ -static int enqueue(struct most_interface *most_iface, - int ch_idx, struct mbo *mbo) -{ - struct hdm_i2c *dev = to_hdm(most_iface); - int ret; - - BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS); - - if (ch_idx == CH_RX) { - /* RX */ - if (!polling_rate) - disable_irq(dev->client->irq); - cancel_delayed_work_sync(&dev->rx.dwork); - list_add_tail(&mbo->list, &dev->rx.list); - if (dev->rx.int_disabled || polling_rate) - pending_rx_work(&dev->rx.dwork.work); - if (!polling_rate) - enable_irq(dev->client->irq); - } else { - /* TX */ - ret = i2c_master_send(dev->client, mbo->virt_address, - mbo->buffer_length); - if (ret <= 0) { - mbo->processed_length = 0; - mbo->status = MBO_E_INVAL; - } else { - mbo->processed_length = mbo->buffer_length; - mbo->status = MBO_SUCCESS; - } - mbo->complete(mbo); - } - - return 0; -} - -/** - * poison_channel - called from MOST core to poison buffers of a channel - * @most_iface: pointer to the interface the channel to be poisoned belongs to - * @ch_idx: corresponding channel ID - * - * Return 0 on success, negative on failure. - * - * If channel direction is RX, complete the buffers in list with - * status MBO_E_CLOSE - */ -static int poison_channel(struct most_interface *most_iface, - int ch_idx) -{ - struct hdm_i2c *dev = to_hdm(most_iface); - struct mbo *mbo; - - BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS); - - if (ch_idx == CH_RX) { - if (!polling_rate) - free_irq(dev->client->irq, dev); - cancel_delayed_work_sync(&dev->rx.dwork); - - while (!list_empty(&dev->rx.list)) { - mbo = list_first_mbo(&dev->rx.list); - list_del(&mbo->list); - - mbo->processed_length = 0; - mbo->status = MBO_E_CLOSE; - mbo->complete(mbo); - } - } - - return 0; -} - -static void do_rx_work(struct hdm_i2c *dev) -{ - struct mbo *mbo; - unsigned char msg[MAX_BUF_SIZE_CONTROL]; - int ret; - u16 pml, data_size; - - /* Read PML (2 bytes) */ - ret = i2c_master_recv(dev->client, msg, 2); - if (ret <= 0) { - pr_err("Failed to receive PML\n"); - return; - } - - pml = (msg[0] << 8) | msg[1]; - if (!pml) - return; - - data_size = pml + 2; - - /* Read the whole message, including PML */ - ret = i2c_master_recv(dev->client, msg, data_size); - if (ret <= 0) { - pr_err("Failed to receive a Port Message\n"); - return; - } - - mbo = list_first_mbo(&dev->rx.list); - list_del(&mbo->list); - - mbo->processed_length = min(data_size, mbo->buffer_length); - memcpy(mbo->virt_address, msg, mbo->processed_length); - mbo->status = MBO_SUCCESS; - mbo->complete(mbo); -} - -/** - * pending_rx_work - Read pending messages through I2C - * @work: definition of this work item - * - * Invoked by the Interrupt Service Routine, most_irq_handler() - */ -static void pending_rx_work(struct work_struct *work) -{ - struct hdm_i2c *dev = container_of(work, struct hdm_i2c, rx.dwork.work); - - if (list_empty(&dev->rx.list)) - return; - - do_rx_work(dev); - - if (polling_rate) { - schedule_delayed_work(&dev->rx.dwork, dev->rx.delay); - } else { - dev->rx.int_disabled = false; - enable_irq(dev->client->irq); - } -} - -/* - * most_irq_handler - Interrupt Service Routine - * @irq: irq number - * @_dev: private data - * - * Schedules a delayed work - * - * By default the interrupt line behavior is Active Low. Once an interrupt is - * generated by the device, until driver clears the interrupt (by reading - * the PMP message), device keeps the interrupt line in low state. Since i2c - * read is done in work queue, the interrupt line must be disabled temporarily - * to avoid ISR being called repeatedly. Re-enable the interrupt in workqueue, - * after reading the message. - * - * Note: If we use the interrupt line in Falling edge mode, there is a - * possibility to miss interrupts when ISR is getting executed. - * - */ -static irqreturn_t most_irq_handler(int irq, void *_dev) -{ - struct hdm_i2c *dev = _dev; - - disable_irq_nosync(irq); - dev->rx.int_disabled = true; - schedule_delayed_work(&dev->rx.dwork, 0); - - return IRQ_HANDLED; -} - -/* - * i2c_probe - i2c probe handler - * @client: i2c client device structure - * @id: i2c client device id - * - * Return 0 on success, negative on failure. - * - * Register the i2c client device as a MOST interface - */ -static int i2c_probe(struct i2c_client *client) -{ - struct hdm_i2c *dev; - int ret, i; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - /* ID format: i2c-<bus>-<address> */ - snprintf(dev->name, sizeof(dev->name), "i2c-%d-%04x", - client->adapter->nr, client->addr); - - for (i = 0; i < NUM_CHANNELS; i++) { - dev->capabilities[i].data_type = MOST_CH_CONTROL; - dev->capabilities[i].num_buffers_packet = MAX_BUFFERS_CONTROL; - dev->capabilities[i].buffer_size_packet = MAX_BUF_SIZE_CONTROL; - } - dev->capabilities[CH_RX].direction = MOST_CH_RX; - dev->capabilities[CH_RX].name_suffix = "rx"; - dev->capabilities[CH_TX].direction = MOST_CH_TX; - dev->capabilities[CH_TX].name_suffix = "tx"; - - dev->most_iface.interface = ITYPE_I2C; - dev->most_iface.description = dev->name; - dev->most_iface.num_channels = NUM_CHANNELS; - dev->most_iface.channel_vector = dev->capabilities; - dev->most_iface.configure = configure_channel; - dev->most_iface.enqueue = enqueue; - dev->most_iface.poison_channel = poison_channel; - - INIT_LIST_HEAD(&dev->rx.list); - - INIT_DELAYED_WORK(&dev->rx.dwork, pending_rx_work); - - dev->client = client; - i2c_set_clientdata(client, dev); - - ret = most_register_interface(&dev->most_iface); - if (ret) { - pr_err("Failed to register i2c as a MOST interface\n"); - kfree(dev); - return ret; - } - - return 0; -} - -/* - * i2c_remove - i2c remove handler - * @client: i2c client device structure - * - * Return 0 on success. - * - * Unregister the i2c client device as a MOST interface - */ -static void i2c_remove(struct i2c_client *client) -{ - struct hdm_i2c *dev = i2c_get_clientdata(client); - - most_deregister_interface(&dev->most_iface); - kfree(dev); -} - -static const struct i2c_device_id i2c_id[] = { - { "most_i2c" }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(i2c, i2c_id); - -static struct i2c_driver i2c_driver = { - .driver = { - .name = "hdm_i2c", - }, - .probe = i2c_probe, - .remove = i2c_remove, - .id_table = i2c_id, -}; - -module_i2c_driver(i2c_driver); - -MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>"); -MODULE_DESCRIPTION("I2C Hardware Dependent Module"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c index 575233fa1677..2db57795ea2f 100644 --- a/drivers/staging/nvec/nvec_ps2.c +++ b/drivers/staging/nvec/nvec_ps2.c @@ -23,14 +23,6 @@ #define DISABLE_MOUSE 0xf5 #define PSMOUSE_RST 0xff -#ifdef NVEC_PS2_DEBUG -#define NVEC_PHD(str, buf, len) \ - print_hex_dump(KERN_DEBUG, str, DUMP_PREFIX_NONE, \ - 16, 1, buf, len, false) -#else -#define NVEC_PHD(str, buf, len) do { } while (0) -#endif - enum ps2_subcmds { SEND_COMMAND = 1, RECEIVE_N, @@ -70,18 +62,14 @@ static int nvec_ps2_notifier(struct notifier_block *nb, case NVEC_PS2_EVT: for (i = 0; i < msg[1]; i++) serio_interrupt(ps2_dev.ser_dev, msg[2 + i], 0); - NVEC_PHD("ps/2 mouse event: ", &msg[2], msg[1]); return NOTIFY_STOP; case NVEC_PS2: if (msg[2] == 1) { for (i = 0; i < (msg[1] - 2); i++) serio_interrupt(ps2_dev.ser_dev, msg[i + 4], 0); - NVEC_PHD("ps/2 mouse reply: ", &msg[4], msg[1] - 2); } - else if (msg[1] != 2) /* !ack */ - NVEC_PHD("unhandled mouse event: ", msg, msg[1] + 2); return NOTIFY_STOP; } diff --git a/drivers/staging/rtl8723bs/core/rtw_ap.c b/drivers/staging/rtl8723bs/core/rtw_ap.c index 0908f2234f67..67197c7d4a4d 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ap.c +++ b/drivers/staging/rtl8723bs/core/rtw_ap.c @@ -391,8 +391,6 @@ void update_bmc_sta(struct adapter *padapter) memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); - /* psta->dot118021XPrivacy = _NO_PRIVACY_;//!!! remove it, because it has been set before this. */ - /* prepare for add_RATid */ supportRateNum = rtw_get_rateset_len((u8 *)&pcur_network->supported_rates); network_type = rtw_check_network_type((u8 *)&pcur_network->supported_rates, @@ -436,7 +434,6 @@ void update_bmc_sta(struct adapter *padapter) spin_lock_bh(&psta->lock); psta->state = _FW_LINKED; spin_unlock_bh(&psta->lock); - } } @@ -480,14 +477,14 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) /* check if sta supports rx ampdu */ phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable; - phtpriv_sta->rx_ampdu_min_spacing = ( - phtpriv_sta->ht_cap.ampdu_params_info & IEEE80211_HT_CAP_AMPDU_DENSITY - ) >> 2; + phtpriv_sta->rx_ampdu_min_spacing = + (phtpriv_sta->ht_cap.ampdu_params_info & + IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; /* bwmode */ - if (( - phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info - ) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH)) + if ((phtpriv_sta->ht_cap.cap_info & + phtpriv_ap->ht_cap.cap_info) & + cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH)) psta->bw_mode = CHANNEL_WIDTH_40; else psta->bw_mode = CHANNEL_WIDTH_20; @@ -498,15 +495,15 @@ void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset; /* check if sta support s Short GI 20M */ - if (( - phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info - ) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) + if ((phtpriv_sta->ht_cap.cap_info & + phtpriv_ap->ht_cap.cap_info) & + cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) phtpriv_sta->sgi_20m = true; /* check if sta support s Short GI 40M */ - if (( - phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info - ) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) { + if ((phtpriv_sta->ht_cap.cap_info & + phtpriv_ap->ht_cap.cap_info) & + cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) { if (psta->bw_mode == CHANNEL_WIDTH_40) /* according to psta->bw_mode */ phtpriv_sta->sgi_40m = true; else @@ -625,9 +622,9 @@ static void update_hw_ht_param(struct adapter *padapter) /* */ /* Config SM Power Save setting */ /* */ - pmlmeinfo->SM_PS = (le16_to_cpu( - pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info - ) & 0x0C) >> 2; + pmlmeinfo->SM_PS = + (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & + 0x0C) >> 2; /* */ /* Config current HT Protection mode. */ @@ -658,9 +655,12 @@ void start_bss_network(struct adapter *padapter) cur_bwmode = CHANNEL_WIDTH_20; cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; - /* check if there is wps ie, */ - /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */ - /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */ + /* + * check if there is wps ie, + * if there is wpsie in beacon, + * the hostapd will update beacon twice when stating hostapd, + * and at first time the security ie (RSN/WPA IE) will not include in beacon. + */ if (!rtw_get_wps_ie(pnetwork->ies + _FIXED_IE_LENGTH_, pnetwork->ie_length - _FIXED_IE_LENGTH_, NULL, NULL)) pmlmeext->bstart_bss = true; @@ -705,9 +705,8 @@ void start_bss_network(struct adapter *padapter) rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm)); /* Set Security */ - val8 = ( - psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X - ) ? 0xcc : 0xcf; + val8 = (psecuritypriv->dot11AuthAlgrthm == + dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf; rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); /* Beacon Control related register */ @@ -778,14 +777,12 @@ void start_bss_network(struct adapter *padapter) update_wireless_mode(padapter); /* update RRSR after set channel and bandwidth */ - UpdateBrateTbl(padapter, pnetwork->supported_rates); + update_basic_rate_table(padapter, pnetwork->supported_rates); rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->supported_rates); /* update capability after cur_wireless_mode updated */ - update_capinfo( - padapter, - rtw_get_capability((struct wlan_bssid_ex *)pnetwork) - ); + update_capinfo(padapter, + rtw_get_capability((struct wlan_bssid_ex *)pnetwork)); if (pmlmeext->bstart_bss) { update_beacon(padapter, WLAN_EID_TIM, NULL, true); @@ -841,7 +838,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) memcpy(pbss_network->mac_address, myid(&padapter->eeprompriv), ETH_ALEN); /* beacon interval */ - p = rtw_get_beacon_interval_from_ie(ie);/* ie + 8; 8: TimeStamp, 2: Beacon Interval 2:Capability */ + /* ie + 8; 8: TimeStamp, 2: Beacon Interval 2:Capability */ + p = rtw_get_beacon_interval_from_ie(ie); /* pbss_network->configuration.beacon_period = le16_to_cpu(*(unsigned short*)p); */ pbss_network->configuration.beacon_period = get_unaligned_le16(p); @@ -851,12 +849,10 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) cap = get_unaligned_le16(ie); /* SSID */ - p = rtw_get_ie( - ie + _BEACON_IE_OFFSET_, - WLAN_EID_SSID, - &ie_len, - (pbss_network->ie_length - _BEACON_IE_OFFSET_) - ); + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, + WLAN_EID_SSID, + &ie_len, + (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { memset(&pbss_network->ssid, 0, sizeof(struct ndis_802_11_ssid)); memcpy(pbss_network->ssid.ssid, (p + 2), ie_len); @@ -866,11 +862,9 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) /* channel */ channel = 0; pbss_network->configuration.length = 0; - p = rtw_get_ie( - ie + _BEACON_IE_OFFSET_, - WLAN_EID_DS_PARAMS, &ie_len, - (pbss_network->ie_length - _BEACON_IE_OFFSET_) - ); + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, + WLAN_EID_DS_PARAMS, &ie_len, + (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) channel = *(p + 2); @@ -878,24 +872,20 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX); /* get supported rates */ - p = rtw_get_ie( - ie + _BEACON_IE_OFFSET_, - WLAN_EID_SUPP_RATES, - &ie_len, - (pbss_network->ie_length - _BEACON_IE_OFFSET_) - ); + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, + WLAN_EID_SUPP_RATES, + &ie_len, + (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p) { memcpy(supportRate, p + 2, ie_len); supportRateNum = ie_len; } /* get ext_supported rates */ - p = rtw_get_ie( - ie + _BEACON_IE_OFFSET_, - WLAN_EID_EXT_SUPP_RATES, - &ie_len, - pbss_network->ie_length - _BEACON_IE_OFFSET_ - ); + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, + WLAN_EID_EXT_SUPP_RATES, + &ie_len, + pbss_network->ie_length - _BEACON_IE_OFFSET_); if (p) { memcpy(supportRate + supportRateNum, p + 2, ie_len); supportRateNum += ie_len; @@ -906,12 +896,10 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) rtw_set_supported_rate(pbss_network->supported_rates, network_type); /* parsing ERP_IE */ - p = rtw_get_ie( - ie + _BEACON_IE_OFFSET_, - WLAN_EID_ERP_INFO, - &ie_len, - (pbss_network->ie_length - _BEACON_IE_OFFSET_) - ); + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, + WLAN_EID_ERP_INFO, + &ie_len, + (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) ERP_IE_handler(padapter, (struct ndis_80211_var_ie *)p); @@ -927,20 +915,16 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) group_cipher = 0; pairwise_cipher = 0; psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_; psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_; - p = rtw_get_ie( - ie + _BEACON_IE_OFFSET_, - WLAN_EID_RSN, - &ie_len, - (pbss_network->ie_length - _BEACON_IE_OFFSET_) - ); + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, + WLAN_EID_RSN, + &ie_len, + (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { - if (rtw_parse_wpa2_ie( - p, - ie_len + 2, - &group_cipher, - &pairwise_cipher, - NULL - ) == _SUCCESS) { + if (rtw_parse_wpa2_ie(p, + ie_len + 2, + &group_cipher, + &pairwise_cipher, + NULL) == _SUCCESS) { psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ @@ -957,20 +941,16 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) psecuritypriv->wpa_group_cipher = _NO_PRIVACY_; psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_; for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) { - p = rtw_get_ie( - p, - WLAN_EID_VENDOR_SPECIFIC, - &ie_len, - (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)) - ); + p = rtw_get_ie(p, + WLAN_EID_VENDOR_SPECIFIC, + &ie_len, + (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2))); if ((p) && (!memcmp(p + 2, OUI1, 4))) { - if (rtw_parse_wpa_ie( - p, - ie_len + 2, - &group_cipher, - &pairwise_cipher, - NULL - ) == _SUCCESS) { + if (rtw_parse_wpa_ie(p, + ie_len + 2, + &group_cipher, + &pairwise_cipher, + NULL) == _SUCCESS) { psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ @@ -993,12 +973,11 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pmlmepriv->qospriv.qos_option = 0; if (pregistrypriv->wmm_enable) { for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) { - p = rtw_get_ie( - p, - WLAN_EID_VENDOR_SPECIFIC, - &ie_len, - (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)) - ); + p = rtw_get_ie(p, + WLAN_EID_VENDOR_SPECIFIC, + &ie_len, + (pbss_network->ie_length - + _BEACON_IE_OFFSET_ - (ie_len + 2))); if ((p) && !memcmp(p + 2, WMM_PARA_IE, 6)) { pmlmepriv->qospriv.qos_option = 1; @@ -1020,12 +999,10 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) } /* parsing HT_CAP_IE */ - p = rtw_get_ie( - ie + _BEACON_IE_OFFSET_, - WLAN_EID_HT_CAPABILITY, - &ie_len, - (pbss_network->ie_length - _BEACON_IE_OFFSET_) - ); + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, + WLAN_EID_HT_CAPABILITY, + &ie_len, + (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { u8 max_rx_ampdu_factor = 0; struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p + 2); @@ -1052,9 +1029,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_RX)) pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_RX_STBC_3R)); - pht_cap->ampdu_params_info &= ~( - IEEE80211_HT_CAP_AMPDU_FACTOR | IEEE80211_HT_CAP_AMPDU_DENSITY - ); + pht_cap->ampdu_params_info &= ~(IEEE80211_HT_CAP_AMPDU_FACTOR | + IEEE80211_HT_CAP_AMPDU_DENSITY); if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) { @@ -1065,14 +1041,12 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) 0x00); } - rtw_hal_get_def_var( - padapter, - HW_VAR_MAX_RX_AMPDU_FACTOR, - &max_rx_ampdu_factor - ); - pht_cap->ampdu_params_info |= ( - IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor - ); /* set Max Rx AMPDU size to 64K */ + rtw_hal_get_def_var(padapter, + HW_VAR_MAX_RX_AMPDU_FACTOR, + &max_rx_ampdu_factor); + /* set Max Rx AMPDU size to 64K */ + pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & + max_rx_ampdu_factor); pht_cap->mcs.rx_mask[0] = 0xff; pht_cap->mcs.rx_mask[1] = 0x0; @@ -1081,12 +1055,10 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) } /* parsing HT_INFO_IE */ - p = rtw_get_ie( - ie + _BEACON_IE_OFFSET_, - WLAN_EID_HT_OPERATION, - &ie_len, - (pbss_network->ie_length - _BEACON_IE_OFFSET_) - ); + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, + WLAN_EID_HT_OPERATION, + &ie_len, + (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) pHT_info_ie = p; @@ -1128,9 +1100,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) HT_info_handler(padapter, (struct ndis_80211_var_ie *)pHT_info_ie); } - pbss_network->length = get_wlan_bssid_ex_sz( - (struct wlan_bssid_ex *)pbss_network - ); + pbss_network->length = + get_wlan_bssid_ex_sz((struct wlan_bssid_ex *)pbss_network); /* issue beacon to start bss network */ /* start_bss_network(padapter, (u8 *)pbss_network); */ @@ -1147,7 +1118,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) /* update AP's sta info */ update_ap_info(padapter, psta); - psta->state |= WIFI_AP_STATE; /* Aries, add, fix bug of flush_cam_entry at STOP AP mode , 0724 */ + psta->state |= WIFI_AP_STATE; rtw_indicate_connect(padapter); pmlmepriv->cur_network.join_res = true;/* for check if already set beacon */ @@ -1237,10 +1208,8 @@ void rtw_acl_remove_sta(struct adapter *padapter, u8 *addr) list_for_each_safe(plist, tmp, phead) { paclnode = list_entry(plist, struct rtw_wlan_acl_node, list); - if ( - !memcmp(paclnode->addr, addr, ETH_ALEN) || - is_broadcast_ether_addr(addr) - ) { + if (!memcmp(paclnode->addr, addr, ETH_ALEN) || + is_broadcast_ether_addr(addr)) { if (paclnode->valid) { paclnode->valid = false; @@ -1252,7 +1221,6 @@ void rtw_acl_remove_sta(struct adapter *padapter, u8 *addr) } spin_unlock_bh(&pacl_node_q->lock); - } u8 rtw_ap_set_pairwise_key(struct adapter *padapter, struct sta_info *psta) @@ -1290,13 +1258,11 @@ exit: return res; } -static int rtw_ap_set_key( - struct adapter *padapter, - u8 *key, - u8 alg, - int keyid, - u8 set_tx -) +static int rtw_ap_set_key(struct adapter *padapter, + u8 *key, + u8 alg, + int keyid, + u8 set_tx) { u8 keylen; struct cmd_obj *pcmd; @@ -1360,13 +1326,11 @@ int rtw_ap_set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid) return rtw_ap_set_key(padapter, key, alg, keyid, 1); } -int rtw_ap_set_wep_key( - struct adapter *padapter, - u8 *key, - u8 keylen, - int keyid, - u8 set_tx -) +int rtw_ap_set_wep_key(struct adapter *padapter, + u8 *key, + u8 keylen, + int keyid, + u8 set_tx) { u8 alg; @@ -1401,21 +1365,18 @@ static void update_bcn_erpinfo_ie(struct adapter *padapter) return; /* parsing ERP_IE */ - p = rtw_get_ie( - ie + _BEACON_IE_OFFSET_, - WLAN_EID_ERP_INFO, - &len, - (pnetwork->ie_length - _BEACON_IE_OFFSET_) - ); + p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, + WLAN_EID_ERP_INFO, + &len, + (pnetwork->ie_length - _BEACON_IE_OFFSET_)); if (p && len > 0) { struct ndis_80211_var_ie *pIE = (struct ndis_80211_var_ie *)p; if (pmlmepriv->num_sta_non_erp == 1) pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION; else - pIE->data[0] &= ~( - RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION - ); + pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT | + RTW_ERP_INFO_USE_PROTECTION); if (pmlmepriv->num_sta_no_short_preamble > 0) pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE; @@ -1461,12 +1422,10 @@ static void update_bcn_wps_ie(struct adapter *padapter) unsigned char *ie = pnetwork->ies; u32 ielen = pnetwork->ie_length; - pwps_ie = rtw_get_wps_ie( - ie + _FIXED_IE_LENGTH_, - ielen - _FIXED_IE_LENGTH_, - NULL, - &wps_ielen - ); + pwps_ie = rtw_get_wps_ie(ie + _FIXED_IE_LENGTH_, + ielen - _FIXED_IE_LENGTH_, + NULL, + &wps_ielen); if (!pwps_ie || wps_ielen == 0) return; @@ -1490,7 +1449,7 @@ static void update_bcn_wps_ie(struct adapter *padapter) wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */ if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) { memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2); - pwps_ie += (wps_ielen+2); + pwps_ie += (wps_ielen + 2); if (pbackup_remainder_ie) memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen); @@ -1651,9 +1610,9 @@ static int rtw_ht_operation_update(struct adapter *padapter) if (pmlmepriv->num_sta_no_ht || (pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)) new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; - else if ( - (le16_to_cpu(phtpriv_ap->ht_cap.cap_info) & IEEE80211_HT_CAP_SUP_WIDTH) - && pmlmepriv->num_sta_ht_20mhz) + else if ((le16_to_cpu(phtpriv_ap->ht_cap.cap_info) & + IEEE80211_HT_CAP_SUP_WIDTH) && + pmlmepriv->num_sta_ht_20mhz) new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; else if (pmlmepriv->olbc_ht) new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER; @@ -1874,12 +1833,10 @@ u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta) return beacon_updated; } -u8 ap_free_sta( - struct adapter *padapter, - struct sta_info *psta, - bool active, - u16 reason -) +u8 ap_free_sta(struct adapter *padapter, + struct sta_info *psta, + bool active, + u16 reason) { u8 beacon_updated = false; @@ -1993,6 +1950,7 @@ void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta) add_RATid(padapter, psta, 0);/* DM_RATR_STA_INIT */ } } + /* restore hw setting from sw data structures */ void rtw_ap_restore_network(struct adapter *padapter) { @@ -2007,25 +1965,21 @@ void rtw_ap_restore_network(struct adapter *padapter) rtw_setopmode_cmd(padapter, Ndis802_11APMode, false); - set_channel_bwmode( - padapter, - pmlmeext->cur_channel, - pmlmeext->cur_ch_offset, - pmlmeext->cur_bwmode - ); + set_channel_bwmode(padapter, + pmlmeext->cur_channel, + pmlmeext->cur_ch_offset, + pmlmeext->cur_bwmode); start_bss_network(padapter); if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) || (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) { /* restore group key, WEP keys is restored in ips_leave() */ - rtw_set_key( - padapter, - psecuritypriv, - psecuritypriv->dot118021XGrpKeyid, - 0, - false - ); + rtw_set_key(padapter, + psecuritypriv, + psecuritypriv->dot118021XGrpKeyid, + 0, + false); } spin_lock_bh(&pstapriv->asoc_list_lock); @@ -2126,11 +2080,9 @@ void stop_ap_mode(struct adapter *padapter) pmlmeext->bstart_bss = false; /* reset and init security priv , this can refine with rtw_reset_securitypriv */ - memset( - (unsigned char *)&padapter->securitypriv, - 0, - sizeof(struct security_priv) - ); + memset((unsigned char *)&padapter->securitypriv, + 0, + sizeof(struct security_priv)); padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; diff --git a/drivers/staging/rtl8723bs/core/rtw_efuse.c b/drivers/staging/rtl8723bs/core/rtw_efuse.c index d5c53b614f61..98b15ca10074 100644 --- a/drivers/staging/rtl8723bs/core/rtw_efuse.c +++ b/drivers/staging/rtl8723bs/core/rtw_efuse.c @@ -26,9 +26,6 @@ u8 fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE]; u8 fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN] = {0}; u8 fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN] = {0}; -#define REG_EFUSE_CTRL 0x0030 -#define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */ - /* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */ u8 Efuse_CalculateWordCnts(u8 word_en) diff --git a/drivers/staging/rtl8723bs/core/rtw_ieee80211.c b/drivers/staging/rtl8723bs/core/rtw_ieee80211.c index 53d4c113b19c..8fdeeda88a6d 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8723bs/core/rtw_ieee80211.c @@ -132,30 +132,30 @@ u8 *rtw_set_ie(u8 *pbuf, return pbuf + len + 2; } -/*---------------------------------------------------------------------------- -index: the information element id index, limit is the limit for search ------------------------------------------------------------------------------*/ +/* index: the information element id index, limit is the limit for search */ u8 *rtw_get_ie(u8 *pbuf, signed int index, signed int *len, signed int limit) { signed int tmp, i; u8 *p; - if (limit < 1) + if (limit < 2) return NULL; p = pbuf; i = 0; *len = 0; - while (1) { + while (i + 2 <= limit) { + tmp = *(p + 1); + if (i + 2 + tmp > limit) + break; + if (*p == index) { - *len = *(p + 1); + *len = tmp; return p; } - tmp = *(p + 1); + p += (tmp + 2); i += (tmp + 2); - if (i >= limit) - break; } return NULL; } @@ -560,7 +560,6 @@ int rtw_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwi return ret; } -/* ifdef CONFIG_WAPI_SUPPORT */ int rtw_get_wapi_ie(u8 *in_ie, uint in_len, u8 *wapi_ie, u16 *wapi_len) { int len = 0; @@ -600,7 +599,6 @@ int rtw_get_wapi_ie(u8 *in_ie, uint in_len, u8 *wapi_ie, u16 *wapi_len) return len; } -/* endif */ void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *wpa_ie, u16 *wpa_len) { @@ -769,21 +767,27 @@ static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen, { unsigned int oui; - /* first 3 bytes in vendor specific information element are the IEEE + /* + * first 3 bytes in vendor specific information element are the IEEE * OUI of the vendor. The following byte is used a vendor specific - * sub-type. */ + * sub-type. + */ if (elen < 4) return -1; oui = get_unaligned_be24(pos); switch (oui) { case OUI_MICROSOFT: - /* Microsoft/Wi-Fi information elements are further typed and - * subtyped */ + /* + * Microsoft/Wi-Fi information elements are further typed and + * subtyped + */ switch (pos[3]) { case 1: - /* Microsoft OUI (00:50:F2) with OUI Type 1: - * real WPA information element */ + /* + * Microsoft OUI (00:50:F2) with OUI Type 1: + * real WPA information element + */ elems->wpa_ie = pos; elems->wpa_ie_len = elen; break; diff --git a/drivers/staging/rtl8723bs/core/rtw_io.c b/drivers/staging/rtl8723bs/core/rtw_io.c index 79d543d88278..fe9f94001eed 100644 --- a/drivers/staging/rtl8723bs/core/rtw_io.c +++ b/drivers/staging/rtl8723bs/core/rtw_io.c @@ -5,25 +5,23 @@ * ******************************************************************************/ /* - -The purpose of rtw_io.c - -a. provides the API - -b. provides the protocol engine - -c. provides the software interface between caller and the hardware interface - - -Compiler Flag Option: - -1. CONFIG_SDIO_HCI: - a. USE_SYNC_IRP: Only sync operations are provided. - b. USE_ASYNC_IRP:Both sync/async operations are provided. - -jackson@realtek.com.tw - -*/ + * The purpose of rtw_io.c + * + * a. provides the API + * + * b. provides the protocol engine + * + * c. provides the software interface between caller and the hardware interface + * + * + * Compiler Flag Option: + * + * 1. CONFIG_SDIO_HCI: + * a. USE_SYNC_IRP: Only sync operations are provided. + * b. USE_ASYNC_IRP:Both sync/async operations are provided. + * + * jackson@realtek.com.tw + */ #include <drv_types.h> @@ -135,10 +133,10 @@ int rtw_init_io_priv(struct adapter *padapter, void (*set_intf_ops)(struct adapt } /* -* Increase and check if the continual_io_error of this @param dvobjprive is larger than MAX_CONTINUAL_IO_ERR -* @return true: -* @return false: -*/ + * Increase and check if the continual_io_error of this @param dvobjprive is larger than MAX_CONTINUAL_IO_ERR + * @return true: + * @return false: + */ int rtw_inc_and_chk_continual_io_error(struct dvobj_priv *dvobj) { int error_count = atomic_inc_return(&dvobj->continual_io_error); @@ -149,9 +147,7 @@ int rtw_inc_and_chk_continual_io_error(struct dvobj_priv *dvobj) return false; } -/* -* Set the continual_io_error of this @param dvobjprive to 0 -*/ +/* Set the continual_io_error of this @param dvobjprive to 0 */ void rtw_reset_continual_io_error(struct dvobj_priv *dvobj) { atomic_set(&dvobj->continual_io_error, 0); diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c index c06d990350e6..98704179ad35 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c @@ -214,10 +214,10 @@ void _rtw_free_network_nolock(struct mlme_priv *pmlmepriv, struct wlan_network * } /* - return the wlan_network with the matching addr - - Shall be called under atomic context... to avoid possible racing condition... -*/ + * return the wlan_network with the matching addr + * + * Shall be called under atomic context... to avoid possible racing condition... + */ struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr) { struct list_head *phead, *plist; @@ -319,10 +319,10 @@ void rtw_free_network_nolock(struct adapter *padapter, struct wlan_network *pnet } /* - return the wlan_network with the matching addr - - Shall be called under atomic context... to avoid possible racing condition... -*/ + * return the wlan_network with the matching addr + * + * Shall be called under atomic context... to avoid possible racing condition... + */ struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr) { struct wlan_network *pnetwork = _rtw_find_network(scanned_queue, addr); @@ -476,9 +476,7 @@ static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex } } -/* -Caller must hold pmlmepriv->lock first. -*/ +/* Caller must hold pmlmepriv->lock first. */ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *target) { struct list_head *plist, *phead; @@ -510,8 +508,10 @@ void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *t oldest = pnetwork; } - /* If we didn't find a match, then get a new network slot to initialize - * with this beacon's information */ + /* + * If we didn't find a match, then get a new network slot to initialize + * with this beacon's information + */ if (!target_find) { if (list_empty(&pmlmepriv->free_bss_pool.queue)) { /* If there are no more slots, expire the oldest */ @@ -843,9 +843,7 @@ static void find_network(struct adapter *adapter) rtw_free_network_nolock(adapter, pwlan); } -/* -*rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock -*/ +/* rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock */ void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue) { struct mlme_priv *pmlmepriv = &adapter->mlmepriv; @@ -879,9 +877,7 @@ void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue) rtw_reset_rx_info(pdbgpriv); } -/* -*rtw_indicate_connect: the caller has to lock pmlmepriv->lock -*/ +/* rtw_indicate_connect: the caller has to lock pmlmepriv->lock */ void rtw_indicate_connect(struct adapter *padapter) { struct mlme_priv *pmlmepriv = &padapter->mlmepriv; @@ -908,9 +904,7 @@ void rtw_indicate_connect(struct adapter *padapter) rtw_set_scan_deny(padapter, 3000); } -/* -*rtw_indicate_disconnect: the caller has to lock pmlmepriv->lock -*/ +/* rtw_indicate_disconnect: the caller has to lock pmlmepriv->lock */ void rtw_indicate_disconnect(struct adapter *padapter) { struct mlme_priv *pmlmepriv = &padapter->mlmepriv; @@ -1543,9 +1537,9 @@ void rtw_wmm_event_callback(struct adapter *padapter, u8 *pbuf) } /* -* _rtw_join_timeout_handler - Timeout/failure handler for CMD JoinBss -* @adapter: pointer to struct adapter structure -*/ + * _rtw_join_timeout_handler - Timeout/failure handler for CMD JoinBss + * @adapter: pointer to struct adapter structure + */ void _rtw_join_timeout_handler(struct timer_list *t) { struct adapter *adapter = timer_container_of(adapter, t, @@ -1586,9 +1580,9 @@ void _rtw_join_timeout_handler(struct timer_list *t) } /* -* rtw_scan_timeout_handler - Timeout/Failure handler for CMD SiteSurvey -* @adapter: pointer to struct adapter structure -*/ + * rtw_scan_timeout_handler - Timeout/Failure handler for CMD SiteSurvey + * @adapter: pointer to struct adapter structure + */ void rtw_scan_timeout_handler(struct timer_list *t) { struct adapter *adapter = timer_container_of(adapter, t, @@ -1704,10 +1698,10 @@ void rtw_set_scan_deny(struct adapter *adapter, u32 ms) } /* -* Select a new roaming candidate from the original @param candidate and @param competitor -* @return true: candidate is updated -* @return false: candidate is not updated -*/ + * Select a new roaming candidate from the original @param candidate and @param competitor + * @return true: candidate is updated + * @return false: candidate is not updated + */ static int rtw_check_roaming_candidate(struct mlme_priv *mlme , struct wlan_network **candidate, struct wlan_network *competitor) { @@ -1785,10 +1779,10 @@ exit: } /* -* Select a new join candidate from the original @param candidate and @param competitor -* @return true: candidate is updated -* @return false: candidate is not updated -*/ + * Select a new join candidate from the original @param candidate and @param competitor + * @return true: candidate is updated + * @return false: candidate is not updated + */ static int rtw_check_join_candidate(struct mlme_priv *mlme , struct wlan_network **candidate, struct wlan_network *competitor) { @@ -1829,11 +1823,11 @@ exit: } /* -Calling context: -The caller of the sub-routine will be in critical section... -The caller must hold the following spinlock -pmlmepriv->lock -*/ + * Calling context: + * The caller of the sub-routine will be in critical section... + * The caller must hold the following spinlock + * pmlmepriv->lock + */ int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv) { diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c index a897c433d2b0..ac49bfbaa5bb 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -18,9 +18,7 @@ static struct mlme_handler mlme_sta_tbl[] = { {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq}, {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp}, - /*---------------------------------------------------------- - below 2 are reserved - -----------------------------------------------------------*/ + /* below 2 are reserved */ {0, "DoReserved", &DoReserved}, {0, "DoReserved", &DoReserved}, {WIFI_BEACON, "OnBeacon", &OnBeacon}, @@ -50,9 +48,7 @@ static struct action_handler OnAction_tbl[] = { static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; -/************************************************** -OUI definitions for the vendor specific IE -***************************************************/ +/* OUI definitions for the vendor specific IE */ unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01}; unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02}; unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04}; @@ -64,9 +60,7 @@ unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20}; -/******************************************************** -ChannelPlan definitions -*********************************************************/ +/* ChannelPlan definitions */ static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = { {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */ {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */ @@ -187,11 +181,7 @@ int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch) return i; } -/**************************************************************************** - -Following are the initialization functions for WiFi MLME - -*****************************************************************************/ +/* Following are the initialization functions for WiFi MLME */ int init_hw_mlme_ext(struct adapter *padapter) { @@ -507,11 +497,7 @@ void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame) } } -/**************************************************************************** - -Following are the callback functions for each subtype of the management frames - -*****************************************************************************/ +/* Following are the callback functions for each subtype of the management frames */ unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame) { @@ -588,9 +574,11 @@ unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame) p = rtw_get_ie(pframe + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, WLAN_EID_EXT_SUPP_RATES, &ielen, precv_frame->u.hdr.len - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_); if (p && ielen > 0) { - if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D)) - /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */ - *(p + 1) = ielen - 1; + if (p + 2 + ielen < pframe + len) { + if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D)) + /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */ + *(p + 1) = ielen - 1; + } } if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { @@ -1042,6 +1030,9 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame) status = WLAN_STATUS_CHALLENGE_FAIL; goto OnAssocReqFail; } else { + if (ie_len > sizeof(supportRate)) + ie_len = sizeof(supportRate); + memcpy(supportRate, p+2, ie_len); supportRateNum = ie_len; @@ -1049,7 +1040,7 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame) pkt_len - WLAN_HDR_A3_LEN - ie_offset); if (p) { - if (supportRateNum <= sizeof(supportRate)) { + if (supportRateNum + ie_len <= sizeof(supportRate)) { memcpy(supportRate+supportRateNum, p+2, ie_len); supportRateNum += ie_len; } @@ -1062,7 +1053,7 @@ unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame) /* update station supportRate */ pstat->bssratelen = supportRateNum; memcpy(pstat->bssrateset, supportRate, supportRateNum); - UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen); + update_basic_rate_table_soft_ap(pstat->bssrateset, pstat->bssratelen); /* check RSN/WPA/WPS */ pstat->dot8021xalg = 0; @@ -1450,7 +1441,7 @@ unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame) pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */ - UpdateBrateTbl(padapter, pmlmeinfo->network.supported_rates); + update_basic_rate_table(padapter, pmlmeinfo->network.supported_rates); report_assoc_result: if (res > 0) @@ -1950,11 +1941,7 @@ inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv) return _alloc_mgtxmitframe(pxmitpriv, false); } -/**************************************************************************** - -Following are some TX functions for WiFi MLME - -*****************************************************************************/ +/* Following are some TX functions for WiFi MLME */ void update_mgnt_tx_rate(struct adapter *padapter, u8 rate) { @@ -3797,11 +3784,7 @@ unsigned int send_beacon(struct adapter *padapter) return _SUCCESS; } -/**************************************************************************** - -Following are some utility functions for WiFi MLME - -*****************************************************************************/ +/* Following are some utility functions for WiFi MLME */ void site_survey(struct adapter *padapter) { @@ -4392,11 +4375,7 @@ static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid } } -/**************************************************************************** - -Following are the functions to report events - -*****************************************************************************/ +/* Following are the functions to report events */ void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame) { @@ -4692,11 +4671,7 @@ void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int rtw_enqueue_cmd(pcmdpriv, pcmd_obj); } -/**************************************************************************** - -Following are the event callback functions - -*****************************************************************************/ +/* Following are the event callback functions */ /* for sta/adhoc mode */ void update_sta_info(struct adapter *padapter, struct sta_info *psta) @@ -4863,8 +4838,10 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res) rtw_sta_media_status_rpt(padapter, psta, 1); - /* wakeup macid after join bss successfully to ensure - the subsequent data frames can be sent out normally */ + /* + * wakeup macid after join bss successfully to ensure + * the subsequent data frames can be sent out normally + */ rtw_hal_macid_wakeup(padapter, psta->mac_id); } @@ -4940,11 +4917,8 @@ void mlmeext_sta_del_event_callback(struct adapter *padapter) rtw_mlmeext_disconnect(padapter); } -/**************************************************************************** - -Following are the functions for the timer handlers +/* Following are the functions for the timer handlers */ -*****************************************************************************/ void _linked_info_dump(struct adapter *padapter) { int i; @@ -5275,7 +5249,7 @@ u8 createbss_hdl(struct adapter *padapter, u8 *pbuf) /* clear CAM */ flush_all_cam_entry(padapter); - memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, ie_length)); + memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, ie_length)); pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length; if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */ @@ -5339,7 +5313,7 @@ u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf) /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */ pmlmeinfo->VHT_enable = 0; - memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, ie_length)); + memcpy(pnetwork, pbuf, offsetof(struct wlan_bssid_ex, ie_length)); pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length; if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */ diff --git a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c index 7b643ac320f0..0ef788abf403 100644 --- a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c +++ b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c @@ -999,11 +999,11 @@ inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms) } /* -* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend -* @adapter: pointer to struct adapter structure -* @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup -* Return _SUCCESS or _FAIL -*/ + * rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend + * @adapter: pointer to struct adapter structure + * @ips_deffer_ms: the ms will prevent from falling into IPS after wakeup + * Return _SUCCESS or _FAIL + */ int _rtw_pwr_wakeup(struct adapter *padapter, u32 ips_deffer_ms, const char *caller) { diff --git a/drivers/staging/rtl8723bs/core/rtw_security.c b/drivers/staging/rtl8723bs/core/rtw_security.c index 3d99d045f4b6..2f941ffbd465 100644 --- a/drivers/staging/rtl8723bs/core/rtw_security.c +++ b/drivers/staging/rtl8723bs/core/rtw_security.c @@ -30,9 +30,7 @@ const char *security_type_str(u8 value) /* WEP related ===== */ -/* - Need to consider the fragment situation -*/ +/* Need to consider the fragment situation */ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe) { /* exclude ICV */ union { @@ -62,14 +60,14 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe) keylength = psecuritypriv->dot11DefKeylen[psecuritypriv->dot11PrivacyKeyIndex]; for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - iv = pframe+pattrib->hdrlen; + iv = pframe + pattrib->hdrlen; memcpy(&wepkey[0], iv, 3); memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); - payload = pframe+pattrib->iv_len+pattrib->hdrlen; + payload = pframe + pattrib->iv_len + pattrib->hdrlen; - if ((curfragnum+1) == pattrib->nr_frags) { /* the last fragment */ + if ((curfragnum + 1) == pattrib->nr_frags) { /* the last fragment */ - length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; + length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length)); @@ -78,7 +76,7 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe) arc4_crypt(ctx, payload + length, crc.f1, 4); } else { - length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; + length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length)); arc4_setkey(ctx, wepkey, 3 + keylength); arc4_crypt(ctx, payload, payload, length); @@ -107,16 +105,16 @@ void rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe) /* start to decrypt recvframe */ if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) { - iv = pframe+prxattrib->hdrlen; + iv = pframe + prxattrib->hdrlen; /* keyindex =(iv[3]&0x3); */ keyindex = prxattrib->key_index; keylength = psecuritypriv->dot11DefKeylen[keyindex]; memcpy(&wepkey[0], iv, 3); /* memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); */ memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[keyindex].skey[0], keylength); - length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len; + length = ((union recv_frame *)precvframe)->u.hdr.len - prxattrib->hdrlen - prxattrib->iv_len; - payload = pframe+prxattrib->iv_len+prxattrib->hdrlen; + payload = pframe + prxattrib->iv_len + prxattrib->hdrlen; /* decrypt payload include icv */ arc4_setkey(ctx, wepkey, 3 + keylength); @@ -174,7 +172,7 @@ void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key) void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b) { /* Append the byte to our word-sized buffer */ - pmicdata->M |= ((unsigned long)b) << (8*pmicdata->nBytesInM); + pmicdata->M |= ((unsigned long)b) << (8 * pmicdata->nBytesInM); pmicdata->nBytesInM++; /* Process the word if it is full. */ if (pmicdata->nBytesInM >= 4) { @@ -261,7 +259,7 @@ void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_cod #define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8)) /* select the Nth 16-bit word of the temporal key unsigned char array TK[] */ -#define TK16(N) Mk16(tk[2*(N)+1], tk[2*(N)]) +#define TK16(N) Mk16(tk[2 * (N) + 1], tk[2 * (N)]) /* S-box lookup: 16 bits --> 16 bits */ #define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)]) @@ -343,23 +341,20 @@ static const unsigned short Sbox1[2][256] = { /* Sbox for hash (can be in R } }; - /* -********************************************************************** -* Routine: Phase 1 -- generate P1K, given TA, TK, IV32 -* -* Inputs: -* tk[] = temporal key [128 bits] -* ta[] = transmitter's MAC address [ 48 bits] -* iv32 = upper 32 bits of IV [ 32 bits] -* Output: -* p1k[] = Phase 1 key [ 80 bits] -* -* Note: -* This function only needs to be called every 2**16 packets, -* although in theory it could be called every packet. -* -********************************************************************** -*/ +/* + * Routine: Phase 1 -- generate P1K, given TA, TK, IV32 + * + * Inputs: + * tk[] = temporal key [128 bits] + * ta[] = transmitter's MAC address [ 48 bits] + * iv32 = upper 32 bits of IV [ 32 bits] + * Output: + * p1k[] = Phase 1 key [ 80 bits] + * + * Note: + * This function only needs to be called every 2**16 packets, + * although in theory it could be called every packet. + */ static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32) { signed int i; @@ -375,39 +370,36 @@ static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32) /* size on the 80-bit block P1K[], using the 128-bit key TK[] */ for (i = 0; i < PHASE1_LOOP_CNT; i++) { /* Each add operation here is mod 2**16 */ - p1k[0] += _S_(p1k[4] ^ TK16((i&1)+0)); - p1k[1] += _S_(p1k[0] ^ TK16((i&1)+2)); - p1k[2] += _S_(p1k[1] ^ TK16((i&1)+4)); - p1k[3] += _S_(p1k[2] ^ TK16((i&1)+6)); - p1k[4] += _S_(p1k[3] ^ TK16((i&1)+0)); + p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0)); + p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2)); + p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4)); + p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6)); + p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0)); p1k[4] += (unsigned short)i; /* avoid "slide attacks" */ } } /* -********************************************************************** -* Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16 -* -* Inputs: -* tk[] = Temporal key [128 bits] -* p1k[] = Phase 1 output key [ 80 bits] -* iv16 = low 16 bits of IV counter [ 16 bits] -* Output: -* rc4key[] = the key used to encrypt the packet [128 bits] -* -* Note: -* The value {TA, IV32, IV16} for Phase1/Phase2 must be unique -* across all packets using the same key TK value. Then, for a -* given value of TK[], this TKIP48 construction guarantees that -* the final RC4KEY value is unique across all packets. -* -* Suggested implementation optimization: if PPK[] is "overlaid" -* appropriately on RC4KEY[], there is no need for the final -* for loop below that copies the PPK[] result into RC4KEY[]. -* -********************************************************************** -*/ + * Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16 + * + * Inputs: + * tk[] = Temporal key [128 bits] + * p1k[] = Phase 1 output key [ 80 bits] + * iv16 = low 16 bits of IV counter [ 16 bits] + * Output: + * rc4key[] = the key used to encrypt the packet [128 bits] + * + * Note: + * The value {TA, IV32, IV16} for Phase1/Phase2 must be unique + * across all packets using the same key TK value. Then, for a + * given value of TK[], this TKIP48 construction guarantees that + * the final RC4KEY value is unique across all packets. + * + * Suggested implementation optimization: if PPK[] is "overlaid" + * appropriately on RC4KEY[], there is no need for the final + * for loop below that copies the PPK[] result into RC4KEY[]. + */ static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16) { signed int i; @@ -417,7 +409,7 @@ static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16) for (i = 0; i < 5; i++) PPK[i] = p1k[i]; /* first, copy P1K to PPK */ - PPK[5] = p1k[4]+iv16; /* next, add in IV16 */ + PPK[5] = p1k[4] + iv16; /* next, add in IV16 */ /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */ PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */ @@ -448,8 +440,8 @@ static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16) /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */ for (i = 0; i < 6; i++) { - rc4key[4+2*i] = Lo8(PPK[i]); - rc4key[5+2*i] = Hi8(PPK[i]); + rc4key[4 + 2 * i] = Lo8(PPK[i]); + rc4key[5 + 2 * i] = Hi8(PPK[i]); } } @@ -492,20 +484,20 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe) prwskey = pattrib->dot118021x_UncstKey.skey; for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - iv = pframe+pattrib->hdrlen; - payload = pframe+pattrib->iv_len+pattrib->hdrlen; + iv = pframe + pattrib->hdrlen; + payload = pframe + pattrib->iv_len + pattrib->hdrlen; GET_TKIP_PN(iv, dot11txpn); pnl = (u16)(dot11txpn.val); - pnh = (u32)(dot11txpn.val>>16); + pnh = (u32)(dot11txpn.val >> 16); phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh); phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl); - if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */ - length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; + if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */ + length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length)); arc4_setkey(ctx, rc4key, 16); @@ -513,7 +505,7 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe) arc4_crypt(ctx, payload + length, crc.f1, 4); } else { - length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; + length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; crc.f0 = cpu_to_le32(~crc32_le(~0, payload, length)); arc4_setkey(ctx, rc4key, 16); @@ -601,14 +593,14 @@ u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe) prwskey = &stainfo->dot118021x_UncstKey.skey[0]; } - iv = pframe+prxattrib->hdrlen; - payload = pframe+prxattrib->iv_len+prxattrib->hdrlen; - length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len; + iv = pframe + prxattrib->hdrlen; + payload = pframe + prxattrib->iv_len + prxattrib->hdrlen; + length = ((union recv_frame *)precvframe)->u.hdr.len - prxattrib->hdrlen - prxattrib->iv_len; GET_TKIP_PN(iv, dot11txpn); pnl = (u16)(dot11txpn.val); - pnh = (u32)(dot11txpn.val>>16); + pnh = (u32)(dot11txpn.val >> 16); phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh); phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl); @@ -758,7 +750,7 @@ static void construct_mic_header2(u8 *mic_header2, if (!qc_exists && a4_exists) { for (i = 0; i < 6; i++) - mic_header2[8+i] = mpdu[24+i]; /* A4 */ + mic_header2[8 + i] = mpdu[24 + i]; /* A4 */ } if (qc_exists && !a4_exists) { @@ -768,7 +760,7 @@ static void construct_mic_header2(u8 *mic_header2, if (qc_exists && a4_exists) { for (i = 0; i < 6; i++) - mic_header2[8+i] = mpdu[24+i]; /* A4 */ + mic_header2[8 + i] = mpdu[24 + i]; /* A4 */ mic_header2[14] = mpdu[30] & 0x0f; mic_header2[15] = mpdu[31] & 0x00; @@ -839,16 +831,16 @@ static signed int aes_cipher(u8 *key, uint hdrlen, uint frtype = GetFrameType(pframe); uint frsubtype = GetFrameSubType(pframe); - frsubtype = frsubtype>>4; + frsubtype = frsubtype >> 4; if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN)) a4_exists = 0; else a4_exists = 1; - if (((frtype|frsubtype) == WIFI_DATA_CFACK) || - ((frtype|frsubtype) == WIFI_DATA_CFPOLL) || - ((frtype|frsubtype) == WIFI_DATA_CFACKPOLL)) { + if (((frtype | frsubtype) == WIFI_DATA_CFACK) || + ((frtype | frsubtype) == WIFI_DATA_CFPOLL) || + ((frtype | frsubtype) == WIFI_DATA_CFACKPOLL)) { qc_exists = 1; if (hdrlen != WLAN_HDR_A3_QOS_LEN) hdrlen += 2; @@ -867,11 +859,11 @@ static signed int aes_cipher(u8 *key, uint hdrlen, } pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen+1]; - pn_vector[2] = pframe[hdrlen+4]; - pn_vector[3] = pframe[hdrlen+5]; - pn_vector[4] = pframe[hdrlen+6]; - pn_vector[5] = pframe[hdrlen+7]; + pn_vector[1] = pframe[hdrlen + 1]; + pn_vector[2] = pframe[hdrlen + 4]; + pn_vector[3] = pframe[hdrlen + 5]; + pn_vector[4] = pframe[hdrlen + 6]; + pn_vector[5] = pframe[hdrlen + 7]; construct_mic_iv(mic_iv, qc_exists, @@ -927,12 +919,12 @@ static signed int aes_cipher(u8 *key, uint hdrlen, /* Insert MIC into payload */ for (j = 0; j < 8; j++) - pframe[payload_index+j] = mic[j]; + pframe[payload_index + j] = mic[j]; payload_index = hdrlen + 8; for (i = 0; i < num_blocks; i++) { construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, /* message, */ - pn_vector, i+1, frtype); + pn_vector, i + 1, frtype); /* add for CONFIG_IEEE80211W, none 11w also can use */ aes128k128d(key, ctr_preload, aes_out); crypto_xor_cpy(chain_buffer, aes_out, &pframe[payload_index], 16); @@ -944,13 +936,13 @@ static signed int aes_cipher(u8 *key, uint hdrlen, /* If there is a short final block, then pad it,*/ /* encrypt it and copy the unpadded part back */ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, /* message, */ - pn_vector, num_blocks+1, frtype); + pn_vector, num_blocks + 1, frtype); /* add for CONFIG_IEEE80211W, none 11w also can use */ for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index+j]; + padded_buffer[j] = pframe[payload_index + j]; aes128k128d(key, ctr_preload, aes_out); crypto_xor_cpy(chain_buffer, aes_out, padded_buffer, 16); @@ -966,7 +958,7 @@ static signed int aes_cipher(u8 *key, uint hdrlen, for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; for (j = 0; j < 8; j++) - padded_buffer[j] = pframe[j+hdrlen+8+plen]; + padded_buffer[j] = pframe[j + hdrlen + 8 + plen]; aes128k128d(key, ctr_preload, aes_out); crypto_xor_cpy(chain_buffer, aes_out, padded_buffer, 16); @@ -1006,12 +998,12 @@ u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe) prwskey = pattrib->dot118021x_UncstKey.skey; for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */ - length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; + if ((curfragnum + 1) == pattrib->nr_frags) { /* 4 the last fragment */ + length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; aes_cipher(prwskey, pattrib->hdrlen, pframe, length); } else { - length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; + length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len; aes_cipher(prwskey, pattrib->hdrlen, pframe, length); pframe += pxmitpriv->frag_len; @@ -1044,13 +1036,13 @@ static signed int aes_decipher(u8 *key, uint hdrlen, uint frtype = GetFrameType(pframe); uint frsubtype = GetFrameSubType(pframe); - frsubtype = frsubtype>>4; + frsubtype = frsubtype >> 4; /* start to decrypt the payload */ - num_blocks = (plen-8) / 16; /* plen including LLC, payload_length and mic) */ + num_blocks = (plen - 8) / 16; /* plen including LLC, payload_length and mic) */ - payload_remainder = (plen-8) % 16; + payload_remainder = (plen - 8) % 16; pn_vector[0] = pframe[hdrlen]; pn_vector[1] = pframe[hdrlen + 1]; @@ -1064,9 +1056,9 @@ static signed int aes_decipher(u8 *key, uint hdrlen, else a4_exists = 1; - if (((frtype|frsubtype) == WIFI_DATA_CFACK) || - ((frtype|frsubtype) == WIFI_DATA_CFPOLL) || - ((frtype|frsubtype) == WIFI_DATA_CFACKPOLL)) { + if (((frtype | frsubtype) == WIFI_DATA_CFACK) || + ((frtype | frsubtype) == WIFI_DATA_CFPOLL) || + ((frtype | frsubtype) == WIFI_DATA_CFACKPOLL)) { qc_exists = 1; if (hdrlen != WLAN_HDR_A3_QOS_LEN) hdrlen += 2; @@ -1105,13 +1097,13 @@ static signed int aes_decipher(u8 *key, uint hdrlen, /* If there is a short final block, then pad it,*/ /* encrypt it and copy the unpadded part back */ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, pframe, pn_vector, - num_blocks+1, frtype); + num_blocks + 1, frtype); /* add for CONFIG_IEEE80211W, none 11w also can use */ for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = pframe[payload_index+j]; + padded_buffer[j] = pframe[payload_index + j]; aes128k128d(key, ctr_preload, aes_out); crypto_xor_cpy(chain_buffer, aes_out, padded_buffer, 16); @@ -1120,25 +1112,25 @@ static signed int aes_decipher(u8 *key, uint hdrlen, } /* start to calculate the mic */ - if ((hdrlen + plen+8) <= MAX_MSG_SIZE) - memcpy((void *)message, pframe, (hdrlen + plen+8)); /* 8 is for ext iv len */ + if ((hdrlen + plen + 8) <= MAX_MSG_SIZE) + memcpy((void *)message, pframe, (hdrlen + plen + 8)); /* 8 is for ext iv len */ pn_vector[0] = pframe[hdrlen]; - pn_vector[1] = pframe[hdrlen+1]; - pn_vector[2] = pframe[hdrlen+4]; - pn_vector[3] = pframe[hdrlen+5]; - pn_vector[4] = pframe[hdrlen+6]; - pn_vector[5] = pframe[hdrlen+7]; + pn_vector[1] = pframe[hdrlen + 1]; + pn_vector[2] = pframe[hdrlen + 4]; + pn_vector[3] = pframe[hdrlen + 5]; + pn_vector[4] = pframe[hdrlen + 6]; + pn_vector[5] = pframe[hdrlen + 7]; - construct_mic_iv(mic_iv, qc_exists, a4_exists, message, plen-8, pn_vector, frtype); + construct_mic_iv(mic_iv, qc_exists, a4_exists, message, plen - 8, pn_vector, frtype); /* add for CONFIG_IEEE80211W, none 11w also can use */ construct_mic_header1(mic_header1, hdrlen, message, frtype); /* add for CONFIG_IEEE80211W, none 11w also can use */ construct_mic_header2(mic_header2, message, a4_exists, qc_exists); - payload_remainder = (plen-8) % 16; - num_blocks = (plen-8) / 16; + payload_remainder = (plen - 8) % 16; + num_blocks = (plen - 8) / 16; /* Find start of payload */ payload_index = (hdrlen + 8); @@ -1173,11 +1165,11 @@ static signed int aes_decipher(u8 *key, uint hdrlen, /* Insert MIC into payload */ for (j = 0; j < 8; j++) - message[payload_index+j] = mic[j]; + message[payload_index + j] = mic[j]; payload_index = hdrlen + 8; for (i = 0; i < num_blocks; i++) { - construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, pn_vector, i+1, + construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, pn_vector, i + 1, frtype); /* add for CONFIG_IEEE80211W, none 11w also can use */ aes128k128d(key, ctr_preload, aes_out); @@ -1190,13 +1182,13 @@ static signed int aes_decipher(u8 *key, uint hdrlen, /* If there is a short final block, then pad it,*/ /* encrypt it and copy the unpadded part back */ construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, pn_vector, - num_blocks+1, frtype); + num_blocks + 1, frtype); /* add for CONFIG_IEEE80211W, none 11w also can use */ for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; for (j = 0; j < payload_remainder; j++) - padded_buffer[j] = message[payload_index+j]; + padded_buffer[j] = message[payload_index + j]; aes128k128d(key, ctr_preload, aes_out); crypto_xor_cpy(chain_buffer, aes_out, padded_buffer, 16); @@ -1211,7 +1203,7 @@ static signed int aes_decipher(u8 *key, uint hdrlen, for (j = 0; j < 16; j++) padded_buffer[j] = 0x00; for (j = 0; j < 8; j++) - padded_buffer[j] = message[j+hdrlen+8+plen-8]; + padded_buffer[j] = message[j + hdrlen + 8 + plen - 8]; aes128k128d(key, ctr_preload, aes_out); crypto_xor_cpy(chain_buffer, aes_out, padded_buffer, 16); @@ -1298,7 +1290,7 @@ u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe) prwskey = &stainfo->dot118021x_UncstKey.skey[0]; } - length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len; + length = ((union recv_frame *)precvframe)->u.hdr.len - prxattrib->hdrlen - prxattrib->iv_len; res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length); @@ -1323,7 +1315,7 @@ u32 rtw_BIP_verify(struct adapter *padapter, u8 *precvframe) __le16 le_tmp; __le64 le_tmp64; - ori_len = pattrib->pkt_len-WLAN_HDR_A3_LEN+BIP_AAD_SIZE; + ori_len = pattrib->pkt_len - WLAN_HDR_A3_LEN + BIP_AAD_SIZE; BIP_AAD = rtw_zmalloc(ori_len); if (!BIP_AAD) @@ -1334,28 +1326,28 @@ u32 rtw_BIP_verify(struct adapter *padapter, u8 *precvframe) /* mapping to wlan header */ pwlanhdr = (struct ieee80211_hdr *)pframe; /* save the frame body + MME */ - memcpy(BIP_AAD+BIP_AAD_SIZE, pframe+WLAN_HDR_A3_LEN, pattrib->pkt_len-WLAN_HDR_A3_LEN); + memcpy(BIP_AAD + BIP_AAD_SIZE, pframe + WLAN_HDR_A3_LEN, pattrib->pkt_len - WLAN_HDR_A3_LEN); /* find MME IE pointer */ - p = rtw_get_ie(BIP_AAD+BIP_AAD_SIZE, WLAN_EID_MMIE, &len, pattrib->pkt_len-WLAN_HDR_A3_LEN); + p = rtw_get_ie(BIP_AAD + BIP_AAD_SIZE, WLAN_EID_MMIE, &len, pattrib->pkt_len - WLAN_HDR_A3_LEN); /* Baron */ if (p) { u16 keyid = 0; u64 temp_ipn = 0; /* save packet number */ - memcpy(&le_tmp64, p+4, 6); + memcpy(&le_tmp64, p + 4, 6); temp_ipn = le64_to_cpu(le_tmp64); /* BIP packet number should bigger than previous BIP packet */ if (temp_ipn <= pmlmeext->mgnt_80211w_IPN_rx) goto BIP_exit; /* copy key index */ - memcpy(&le_tmp, p+2, 2); + memcpy(&le_tmp, p + 2, 2); keyid = le16_to_cpu(le_tmp); if (keyid != padapter->securitypriv.dot11wBIPKeyid) goto BIP_exit; /* clear the MIC field of MME to zero */ - memset(p+2+len-8, 0, 8); + memset(p + 2 + len - 8, 0, 8); /* conscruct AAD, copy frame control field */ memcpy(BIP_AAD, &pwlanhdr->frame_control, 2); @@ -1483,7 +1475,8 @@ static int omac1_aes_128_vector(u8 *key, size_t num_elem, * This is a mode for using block cipher (AES in this case) for authentication. * OMAC1 was standardized with the name CMAC by NIST in a Special Publication * (SP) 800-38B. - * modify for CONFIG_IEEE80211W */ + * modify for CONFIG_IEEE80211W + */ int omac1_aes_128(u8 *key, u8 *data, size_t data_len, u8 *mac) { return omac1_aes_128_vector(key, 1, &data, &data_len, mac); @@ -1515,7 +1508,7 @@ u8 rtw_handle_tkip_countermeasure(struct adapter *adapter, const char *caller) if (securitypriv->btkip_countermeasure) { unsigned long passing_ms = jiffies_to_msecs(jiffies - securitypriv->btkip_countermeasure_time); - if (passing_ms > 60*1000) { + if (passing_ms > 60 * 1000) { netdev_dbg(adapter->pnetdev, "%s(%s) countermeasure time:%lus > 60s\n", caller, ADPT_ARG(adapter), diff --git a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c index d1f6030799cb..3e80d03c4ec9 100644 --- a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c +++ b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c @@ -383,12 +383,6 @@ u32 rtw_free_stainfo(struct adapter *padapter, struct sta_info *psta) /* release mac id for non-bc/mc station, */ rtw_release_macid(pstapriv->padapter, psta); - -/* - spin_lock_bh(&pstapriv->asoc_list_lock); - list_del_init(&psta->asoc_list); - spin_unlock_bh(&pstapriv->asoc_list_lock); -*/ spin_lock_bh(&pstapriv->auth_list_lock); if (!list_empty(&psta->auth_list)) { list_del_init(&psta->auth_list); diff --git a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c index 1def9758852c..5ffefa50699e 100644 --- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c @@ -181,7 +181,7 @@ void set_mcs_rate_by_mask(u8 *mcs_set, u32 mask) mcs_set[3] &= mcs_rate_4r; } -void UpdateBrateTbl(struct adapter *Adapter, u8 *mBratesOS) +void update_basic_rate_table(struct adapter *Adapter, u8 *mBratesOS) { u8 i; u8 rate; @@ -203,7 +203,7 @@ void UpdateBrateTbl(struct adapter *Adapter, u8 *mBratesOS) } } -void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen) +void update_basic_rate_table_soft_ap(u8 *bssrateset, u32 bssratelen) { u8 i; u8 rate; @@ -1021,9 +1021,9 @@ void HTOnAssocRsp(struct adapter *padapter) /* handle A-MPDU parameter field */ /* - AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k - AMPDU_para [4:2]:Min MPDU Start Spacing - */ + * AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k + * AMPDU_para [4:2]:Min MPDU Start Spacing + */ max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03; min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2; @@ -1689,15 +1689,6 @@ void adaptive_early_32k(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len) else pmlmeext->bcn_delay_cnt[delay_ms]++; /* pmlmeext->bcn_delay_ratio[delay_ms] = (pmlmeext->bcn_delay_cnt[delay_ms] * 100) /pmlmeext->bcn_cnt; */ - -/* - - for (i = 0; i<9; i++) - { - pmlmeext->bcn_delay_cnt[i] , i, pmlmeext->bcn_delay_ratio[i]); - } -*/ - /* dump for adaptive_early_32k */ if (pmlmeext->bcn_cnt > 100 && (pmlmeext->adaptive_tsf_done == true)) { u8 ratio_20_delay, ratio_80_delay; diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c index 07e9d3423651..70b5b289f9cb 100644 --- a/drivers/staging/rtl8723bs/hal/hal_com.c +++ b/drivers/staging/rtl8723bs/hal/hal_com.c @@ -663,71 +663,6 @@ void GetHwReg(struct adapter *adapter, u8 variable, u8 *val) } } - - - -u8 SetHalDefVar( - struct adapter *adapter, enum hal_def_variable variable, void *value -) -{ - struct hal_com_data *hal_data = GET_HAL_DATA(adapter); - struct dm_odm_t *odm = &(hal_data->odmpriv); - u8 bResult = _SUCCESS; - - switch (variable) { - case HW_DEF_ODM_DBG_FLAG: - ODM_CmnInfoUpdate(odm, ODM_CMNINFO_DBG_COMP, *((u64 *)value)); - break; - case HW_DEF_ODM_DBG_LEVEL: - ODM_CmnInfoUpdate(odm, ODM_CMNINFO_DBG_LEVEL, *((u32 *)value)); - break; - case HAL_DEF_DBG_DM_FUNC: - { - u8 dm_func = *((u8 *)value); - struct dm_priv *dm = &hal_data->dmpriv; - - if (dm_func == 0) { /* disable all dynamic func */ - odm->SupportAbility = DYNAMIC_FUNC_DISABLE; - } else if (dm_func == 1) {/* disable DIG */ - odm->SupportAbility &= (~DYNAMIC_BB_DIG); - } else if (dm_func == 2) {/* disable High power */ - odm->SupportAbility &= (~DYNAMIC_BB_DYNAMIC_TXPWR); - } else if (dm_func == 3) {/* disable tx power tracking */ - odm->SupportAbility &= (~DYNAMIC_RF_CALIBRATION); - } else if (dm_func == 4) {/* disable BT coexistence */ - dm->DMFlag &= (~DYNAMIC_FUNC_BT); - } else if (dm_func == 5) {/* disable antenna diversity */ - odm->SupportAbility &= (~DYNAMIC_BB_ANT_DIV); - } else if (dm_func == 6) {/* turn on all dynamic func */ - if (!(odm->SupportAbility & DYNAMIC_BB_DIG)) { - struct dig_t *pDigTable = &odm->DM_DigTable; - pDigTable->CurIGValue = rtw_read8(adapter, 0xc50); - } - dm->DMFlag |= DYNAMIC_FUNC_BT; - odm->SupportAbility = DYNAMIC_ALL_FUNC_ENABLE; - } - } - break; - case HAL_DEF_DBG_DUMP_RXPKT: - hal_data->bDumpRxPkt = *((u8 *)value); - break; - case HAL_DEF_DBG_DUMP_TXPKT: - hal_data->bDumpTxPkt = *((u8 *)value); - break; - case HAL_DEF_ANT_DETECT: - hal_data->AntDetection = *((u8 *)value); - break; - default: - netdev_dbg(adapter->pnetdev, - "%s: [WARNING] HAL_DEF_VARIABLE(%d) not defined!\n", - __func__, variable); - bResult = _FAIL; - break; - } - - return bResult; -} - u8 GetHalDefVar( struct adapter *adapter, enum hal_def_variable variable, void *value ) diff --git a/drivers/staging/rtl8723bs/hal/hal_intf.c b/drivers/staging/rtl8723bs/hal/hal_intf.c index 961b0563951d..462553d296ff 100644 --- a/drivers/staging/rtl8723bs/hal/hal_intf.c +++ b/drivers/staging/rtl8723bs/hal/hal_intf.c @@ -115,11 +115,6 @@ void rtw_hal_set_hwreg_with_buf(struct adapter *padapter, u8 variable, u8 *pbuf, SetHwRegWithBuf8723B(padapter, variable, pbuf, len); } -u8 rtw_hal_set_def_var(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue) -{ - return SetHalDefVar8723BSDIO(padapter, eVariable, pValue); -} - u8 rtw_hal_get_def_var(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue) { return GetHalDefVar8723BSDIO(padapter, eVariable, pValue); diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c index 4b36af47f680..639b6da2302b 100644 --- a/drivers/staging/rtl8723bs/hal/odm.c +++ b/drivers/staging/rtl8723bs/hal/odm.c @@ -609,15 +609,12 @@ void ODM_DMWatchdog(struct dm_odm_t *pDM_Odm) /* 8723A or 8189ES platform */ /* NeilChen--2012--08--24-- */ /* Fix Leave LPS issue */ - if ((adapter_to_pwrctl(pDM_Odm->Adapter)->pwr_mode != PS_MODE_ACTIVE) /* in LPS mode */ - /* */ - /* (pDM_Odm->SupportICType & (ODM_RTL8723A))|| */ - /* (pDM_Odm->SupportICType & (ODM_RTL8188E) &&(&&(((pDM_Odm->SupportInterface == ODM_ITRF_SDIO))) */ - /* */ - ) { - odm_DIGbyRSSI_LPS(pDM_Odm); - } else + if (adapter_to_pwrctl(pDM_Odm->Adapter)->pwr_mode != PS_MODE_ACTIVE) { + /* in LPS mode */ + odm_DIGbyRSSI_LPS(pDM_Odm); + } else { odm_DIG(pDM_Odm); + } { struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable; diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c index 63c4ebe9df12..af6cdda8238d 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_cmd.c @@ -7,6 +7,7 @@ #include <drv_types.h> #include <rtl8723b_hal.h> +#include <linux/etherdevice.h> #include "hal_com_h2c.h" #define MAX_H2C_BOX_NUMS 4 @@ -117,8 +118,8 @@ static void ConstructBeacon(struct adapter *padapter, u8 *pframe, u32 *pLength) *(fctrl) = 0; eth_broadcast_addr(pwlanhdr->addr1); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, get_my_bssid(cur_network)); SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); /* pmlmeext->mgnt_seq++; */ @@ -209,10 +210,10 @@ static void ConstructPSPoll(struct adapter *padapter, u8 *pframe, u32 *pLength) SetDuration(pframe, (pmlmeinfo->aid | 0xc000)); /* BSSID. */ - memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network))); /* TA. */ - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); *pLength = 16; } @@ -246,21 +247,21 @@ static void ConstructNullFunctionData( switch (cur_network->network.infrastructure_mode) { case Ndis802_11Infrastructure: SetToDs(fctrl); - memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, StaAddr, ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network))); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, StaAddr); break; case Ndis802_11APMode: SetFrDs(fctrl); - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, StaAddr); + ether_addr_copy(pwlanhdr->addr2, get_my_bssid(&(pmlmeinfo->network))); + ether_addr_copy(pwlanhdr->addr3, myid(&(padapter->eeprompriv))); break; case Ndis802_11IBSS: default: - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); - memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, StaAddr); + ether_addr_copy(pwlanhdr->addr2, myid(&(padapter->eeprompriv))); + ether_addr_copy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network))); break; } @@ -765,9 +766,9 @@ static void ConstructBtNullFunctionData( SetPwrMgt(fctrl); SetFrDs(fctrl); - memcpy(pwlanhdr->addr1, StaAddr, ETH_ALEN); - memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); - memcpy(pwlanhdr->addr3, myid(&padapter->eeprompriv), ETH_ALEN); + ether_addr_copy(pwlanhdr->addr1, StaAddr); + ether_addr_copy(pwlanhdr->addr2, myid(&padapter->eeprompriv)); + ether_addr_copy(pwlanhdr->addr3, myid(&padapter->eeprompriv)); SetDuration(pwlanhdr, 0); SetSeqNum(pwlanhdr, 0); diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c index 18244adad9e0..57c83f332e74 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c @@ -2840,22 +2840,6 @@ void GetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val) } /* Description: - * Change default setting of specified variable. - */ -u8 SetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval) -{ - u8 bResult = _SUCCESS; - - switch (variable) { - default: - bResult = SetHalDefVar(padapter, variable, pval); - break; - } - - return bResult; -} - -/* Description: * Query setting of specified variable. */ u8 GetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval) diff --git a/drivers/staging/rtl8723bs/hal/sdio_halinit.c b/drivers/staging/rtl8723bs/hal/sdio_halinit.c index 7fcb874d0eb3..4e81ef53dc47 100644 --- a/drivers/staging/rtl8723bs/hal/sdio_halinit.c +++ b/drivers/staging/rtl8723bs/hal/sdio_halinit.c @@ -1014,14 +1014,10 @@ static void Hal_EfuseParseMACAddr_8723BS( struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail ) { - u16 i; - u8 sMacAddr[6] = {0x00, 0xE0, 0x4C, 0xb7, 0x23, 0x00}; struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter); if (AutoLoadFail) { -/* sMacAddr[5] = (u8)GetRandomNumber(1, 254); */ - for (i = 0; i < 6; i++) - pEEPROM->mac_addr[i] = sMacAddr[i]; + eth_random_addr(pEEPROM->mac_addr); } else { /* Read Permanent MAC address */ memcpy(pEEPROM->mac_addr, &hwinfo[EEPROM_MAC_ADDR_8723BS], ETH_ALEN); @@ -1236,12 +1232,3 @@ u8 GetHalDefVar8723BSDIO( return bResult; } - -/* */ -/* Description: */ -/* Change default setting of specified variable. */ -/* */ -u8 SetHalDefVar8723BSDIO(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue) -{ - return SetHalDefVar8723B(Adapter, eVariable, pValue); -} diff --git a/drivers/staging/rtl8723bs/hal/sdio_ops.c b/drivers/staging/rtl8723bs/hal/sdio_ops.c index 8736c124f857..0ee50b4a1149 100644 --- a/drivers/staging/rtl8723bs/hal/sdio_ops.c +++ b/drivers/staging/rtl8723bs/hal/sdio_ops.c @@ -997,10 +997,7 @@ u8 HalQueryTxBufferStatus8723BSdio(struct adapter *adapter) return true; } -/* */ -/* Description: */ -/* Query SDIO Local register to get the current number of TX OQT Free Space. */ -/* */ +/* Read the TX OQT free page count from the SDIO local register. */ void HalQueryTxOQTBufferStatus8723BSdio(struct adapter *adapter) { struct hal_com_data *haldata = GET_HAL_DATA(adapter); diff --git a/drivers/staging/rtl8723bs/include/basic_types.h b/drivers/staging/rtl8723bs/include/basic_types.h index 1c2da18e6210..8adb95f9f1e5 100644 --- a/drivers/staging/rtl8723bs/include/basic_types.h +++ b/drivers/staging/rtl8723bs/include/basic_types.h @@ -12,8 +12,7 @@ #define FAIL (-1) #include <linux/types.h> - -#define FIELD_OFFSET(s, field) ((__kernel_ssize_t)&((s *)(0))->field) +#include <linux/stddef.h> #define SIZE_PTR __kernel_size_t #define SSIZE_PTR __kernel_ssize_t diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h index dd9018aa4ee5..f86180dc350c 100644 --- a/drivers/staging/rtl8723bs/include/drv_types.h +++ b/drivers/staging/rtl8723bs/include/drv_types.h @@ -171,13 +171,6 @@ struct registry_priv { u8 hiq_filter; }; - -/* For registry parameters */ -#define RGTRY_OFT(field) ((u32)FIELD_OFFSET(struct registry_priv, field)) -#define RGTRY_SZ(field) sizeof(((struct registry_priv *)0)->field) -#define BSSID_OFT(field) ((u32)FIELD_OFFSET(struct wlan_bssid_ex, field)) -#define BSSID_SZ(field) sizeof(((struct wlan_bssid_ex *) 0)->field) - #include <drv_types_sdio.h> #define GET_PRIMARY_ADAPTER(padapter) (((struct adapter *)padapter)->dvobj->if1) diff --git a/drivers/staging/rtl8723bs/include/hal_com.h b/drivers/staging/rtl8723bs/include/hal_com.h index 7ea9ee2b3975..74d6c892c401 100644 --- a/drivers/staging/rtl8723bs/include/hal_com.h +++ b/drivers/staging/rtl8723bs/include/hal_com.h @@ -138,8 +138,6 @@ void SetHwReg(struct adapter *padapter, u8 variable, u8 *val); void GetHwReg(struct adapter *padapter, u8 variable, u8 *val); void rtw_hal_check_rxfifo_full(struct adapter *adapter); -u8 SetHalDefVar(struct adapter *adapter, enum hal_def_variable variable, - void *value); u8 GetHalDefVar(struct adapter *adapter, enum hal_def_variable variable, void *value); diff --git a/drivers/staging/rtl8723bs/include/hal_com_reg.h b/drivers/staging/rtl8723bs/include/hal_com_reg.h index 9a02ae69d7a4..cf5c15dc2bfd 100644 --- a/drivers/staging/rtl8723bs/include/hal_com_reg.h +++ b/drivers/staging/rtl8723bs/include/hal_com_reg.h @@ -189,10 +189,6 @@ /* Redifine 8192C register definition for compatibility */ /* */ /* */ - -/* TODO: use these definition when using REG_xxx naming rule. */ -/* NOTE: DO NOT Remove these definition. Use later. */ - #define EFUSE_CTRL REG_EFUSE_CTRL /* E-Fuse Control. */ #define EFUSE_TEST REG_EFUSE_TEST /* E-Fuse Test. */ #define MSR (REG_CR + 2) /* Media Status register */ diff --git a/drivers/staging/rtl8723bs/include/hal_intf.h b/drivers/staging/rtl8723bs/include/hal_intf.h index 2fa2382ad5f3..82b60899129d 100644 --- a/drivers/staging/rtl8723bs/include/hal_intf.h +++ b/drivers/staging/rtl8723bs/include/hal_intf.h @@ -199,7 +199,6 @@ void rtw_hal_chip_configure(struct adapter *padapter); void rtw_hal_read_chip_info(struct adapter *padapter); void rtw_hal_read_chip_version(struct adapter *padapter); -u8 rtw_hal_set_def_var(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue); u8 rtw_hal_get_def_var(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue); void rtw_hal_set_odm_var(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet); @@ -262,7 +261,6 @@ void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val); void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val); void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf, int len); u8 GetHalDefVar8723BSDIO(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue); -u8 SetHalDefVar8723BSDIO(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue); void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level); void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter); void Hal_EfusePowerSwitch(struct adapter *padapter, u8 PwrState); diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_hal.h b/drivers/staging/rtl8723bs/include/rtl8723b_hal.h index 2ed1fc8549ec..06e0a549fa9d 100644 --- a/drivers/staging/rtl8723bs/include/rtl8723b_hal.h +++ b/drivers/staging/rtl8723bs/include/rtl8723b_hal.h @@ -223,8 +223,6 @@ void C2HPacketHandler_8723B(struct adapter *padapter, u8 *pbuffer, u16 length); void SetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val); void GetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val); -u8 SetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, - void *pval); u8 GetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval); diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme.h b/drivers/staging/rtl8723bs/include/rtw_mlme.h index 4c15d0194d4f..2a128568c6df 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme.h @@ -18,11 +18,7 @@ #define SCANNING_TIMEOUT 8000 -#ifdef PALTFORM_OS_WINCE -#define SCANQUEUE_LIFETIME 12000000 /* unit:us */ -#else #define SCANQUEUE_LIFETIME 20000 /* 20sec, unit:msec */ -#endif #define WIFI_NULL_STATE 0x00000000 #define WIFI_ASOC_STATE 0x00000001 /* Under Linked state... */ diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h index 53fac838c36a..dd5080056e58 100644 --- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h +++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h @@ -434,8 +434,8 @@ u8 networktype_to_raid_ex(struct adapter *adapter, struct sta_info *psta); void get_rate_set(struct adapter *padapter, unsigned char *pbssrate, int *bssrate_len); void set_mcs_rate_by_mask(u8 *mcs_set, u32 mask); -void UpdateBrateTbl(struct adapter *padapter, u8 *mBratesOS); -void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen); +void update_basic_rate_table(struct adapter *padapter, u8 *mBratesOS); +void update_basic_rate_table_soft_ap(u8 *bssrateset, u32 bssratelen); void Save_DM_Func_Flag(struct adapter *padapter); void Restore_DM_Func_Flag(struct adapter *padapter); diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index 315bab373729..60edeae1cffe 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -1712,7 +1712,8 @@ static int cfg80211_rtw_connect(struct wiphy *wiphy, struct net_device *ndev, if (wep_key_len > 0) { wep_key_len = wep_key_len <= 5 ? 5 : 13; - wep_total_len = wep_key_len + FIELD_OFFSET(struct ndis_802_11_wep, key_material); + wep_total_len = wep_key_len + + offsetof(struct ndis_802_11_wep, key_material); pwep = rtw_malloc(wep_total_len); if (!pwep) { ret = -ENOMEM; diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c index f3caaa857c86..1d0239eef114 100644 --- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c +++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c @@ -490,3 +490,5 @@ static void __exit rtw_drv_halt(void) sdio_unregister_driver(&rtl8723bs_sdio_driver); } module_exit(rtw_drv_halt); + +MODULE_DESCRIPTION("Realtek RTL8723BS SDIO WiFi driver"); diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c index 3659af7e519d..fecd7457e615 100644 --- a/drivers/staging/sm750fb/sm750.c +++ b/drivers/staging/sm750fb/sm750.c @@ -121,8 +121,8 @@ static int lynxfb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor) sm750_hw_cursor_disable(cursor); if (fbcursor->set & FB_CUR_SETSIZE) sm750_hw_cursor_set_size(cursor, - fbcursor->image.width, - fbcursor->image.height); + fbcursor->image.width, + fbcursor->image.height); if (fbcursor->set & FB_CUR_SETPOS) sm750_hw_cursor_set_pos(cursor, @@ -537,8 +537,13 @@ static int lynxfb_ops_setcolreg(unsigned int regno, return -EINVAL; } - if (info->var.grayscale) - red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; + if (info->var.grayscale) { + int lum = (red * 77 + green * 151 + blue * 28) >> 8; + + red = lum; + green = lum; + blue = lum; + } if (var->bits_per_pixel == 8 && info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { diff --git a/drivers/staging/sm750fb/sm750_accel.c b/drivers/staging/sm750fb/sm750_accel.c index b07c1aa68621..046b9282b24a 100644 --- a/drivers/staging/sm750fb/sm750_accel.c +++ b/drivers/staging/sm750fb/sm750_accel.c @@ -89,7 +89,7 @@ int sm750_hw_fillrect(struct lynx_accel *accel, u32 x, u32 y, u32 width, u32 height, u32 color, u32 rop) { - u32 deCtrl; + u32 de_ctrl; if (accel->de_wait() != 0) { /* @@ -121,11 +121,11 @@ int sm750_hw_fillrect(struct lynx_accel *accel, ((width << DE_DIMENSION_X_SHIFT) & DE_DIMENSION_X_MASK) | (height & DE_DIMENSION_Y_ET_MASK)); /* dpr8 */ - deCtrl = DE_CONTROL_STATUS | DE_CONTROL_LAST_PIXEL | + de_ctrl = DE_CONTROL_STATUS | DE_CONTROL_LAST_PIXEL | DE_CONTROL_COMMAND_RECTANGLE_FILL | DE_CONTROL_ROP_SELECT | (rop & DE_CONTROL_ROP_MASK); /* dpr0xc */ - write_dpr(accel, DE_CONTROL, deCtrl); + write_dpr(accel, DE_CONTROL, de_ctrl); return 0; } @@ -284,7 +284,7 @@ int sm750_hw_copyarea(struct lynx_accel *accel, return 0; } -static unsigned int deGetTransparency(struct lynx_accel *accel) +static unsigned int de_get_transparency(struct lynx_accel *accel) { unsigned int de_ctrl; @@ -391,7 +391,7 @@ int sm750_hw_imageblit(struct lynx_accel *accel, const char *pSrcbuf, DE_CONTROL_ROP_SELECT | DE_CONTROL_COMMAND_HOST_WRITE | DE_CONTROL_HOST | DE_CONTROL_STATUS; - write_dpr(accel, DE_CONTROL, de_ctrl | deGetTransparency(accel)); + write_dpr(accel, DE_CONTROL, de_ctrl | de_get_transparency(accel)); /* Write MONO data (line by line) to 2D Engine data port */ for (i = 0; i < height; i++) { diff --git a/drivers/staging/vc04_services/Kconfig b/drivers/staging/vc04_services/Kconfig index ccc8e1588648..2f6d1aaffdb2 100644 --- a/drivers/staging/vc04_services/Kconfig +++ b/drivers/staging/vc04_services/Kconfig @@ -1,56 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 -menuconfig BCM_VIDEOCORE - tristate "Broadcom VideoCore support" - depends on OF - depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE) - default y - help - Support for Broadcom VideoCore services including - the BCM2835 family of products which is used - by the Raspberry PI. - if BCM_VIDEOCORE -config BCM2835_VCHIQ - tristate "BCM2835 VCHIQ" - depends on HAS_DMA - imply VCHIQ_CDEV - help - Broadcom BCM2835 and similar SoCs have a VPU called VideoCore. - This config enables the VCHIQ driver, which implements a - messaging interface between the kernel and the firmware running - on VideoCore. Other drivers use this interface to communicate to - the VPU. More specifically, the VCHIQ driver is used by - audio/video and camera drivers as well as for implementing MMAL - API, which is in turn used by several multimedia services on the - BCM2835 family of SoCs. - - Defaults to Y when the Broadcom Videocore services are included - in the build, N otherwise. - -if BCM2835_VCHIQ - -config VCHIQ_CDEV - bool "VCHIQ Character Driver" - help - Enable the creation of VCHIQ character driver. The cdev exposes - ioctls used by userspace libraries and testing tools to interact - with VideoCore, via the VCHIQ core driver (Check BCM2835_VCHIQ - for more info). - - This can be set to 'N' if the VideoCore communication is not - needed by userspace but only by other kernel modules - (like bcm2835-audio). - - If not sure, set this to 'Y'. - -endif - source "drivers/staging/vc04_services/bcm2835-audio/Kconfig" -source "drivers/staging/vc04_services/bcm2835-camera/Kconfig" - -source "drivers/staging/vc04_services/vchiq-mmal/Kconfig" - endif diff --git a/drivers/staging/vc04_services/Makefile b/drivers/staging/vc04_services/Makefile index dad3789522b8..ba15ec663af0 100644 --- a/drivers/staging/vc04_services/Makefile +++ b/drivers/staging/vc04_services/Makefile @@ -1,17 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_BCM2835_VCHIQ) += vchiq.o - -vchiq-objs := \ - interface/vchiq_arm/vchiq_core.o \ - interface/vchiq_arm/vchiq_arm.o \ - interface/vchiq_arm/vchiq_bus.o \ - interface/vchiq_arm/vchiq_debugfs.o \ - -ifdef CONFIG_VCHIQ_CDEV -vchiq-objs += interface/vchiq_arm/vchiq_dev.o -endif - obj-$(CONFIG_SND_BCM2835) += bcm2835-audio/ -obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-camera/ -obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += vchiq-mmal/ diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c index 0dbe76ee5570..7368b384497f 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c @@ -4,11 +4,12 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/completion.h> + +#include <linux/raspberrypi/vchiq_arm.h> + #include "bcm2835.h" #include "vc_vchi_audioserv_defs.h" -#include "../interface/vchiq_arm/vchiq_arm.h" - struct bcm2835_audio_instance { struct device *dev; unsigned int service_handle; diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c index b74cb104e9de..f292a6618166 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.c @@ -6,7 +6,8 @@ #include <linux/slab.h> #include <linux/module.h> -#include "../interface/vchiq_arm/vchiq_bus.h" +#include <linux/raspberrypi/vchiq_bus.h> + #include "bcm2835.h" static bool enable_hdmi; diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h index 49ec5b496edb..5a1348747ff4 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835.h @@ -5,13 +5,12 @@ #define __SOUND_ARM_BCM2835_H #include <linux/device.h> +#include <linux/raspberrypi/vchiq.h> #include <linux/wait.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm-indirect.h> -#include "../include/linux/raspberrypi/vchiq.h" - #define MAX_SUBSTREAMS (8) #define AVAIL_SUBSTREAMS_MASK (0xff) diff --git a/drivers/staging/vc04_services/bcm2835-camera/Kconfig b/drivers/staging/vc04_services/bcm2835-camera/Kconfig deleted file mode 100644 index 870c9afb223a..000000000000 --- a/drivers/staging/vc04_services/bcm2835-camera/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config VIDEO_BCM2835 - tristate "BCM2835 Camera" - depends on MEDIA_SUPPORT - depends on VIDEO_DEV && (ARCH_BCM2835 || COMPILE_TEST) - select BCM2835_VCHIQ if HAS_DMA - select BCM2835_VCHIQ_MMAL if HAS_DMA - select VIDEOBUF2_VMALLOC - select BTREE - help - Say Y here to enable camera host interface devices for - Broadcom BCM2835 SoC. This operates over the VCHIQ interface - to a service running on VideoCore. diff --git a/drivers/staging/vc04_services/bcm2835-camera/Makefile b/drivers/staging/vc04_services/bcm2835-camera/Makefile deleted file mode 100644 index 203b93899b20..000000000000 --- a/drivers/staging/vc04_services/bcm2835-camera/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -bcm2835-v4l2-$(CONFIG_VIDEO_BCM2835) := \ - bcm2835-camera.o \ - controls.o - -obj-$(CONFIG_VIDEO_BCM2835) += bcm2835-v4l2.o diff --git a/drivers/staging/vc04_services/bcm2835-camera/TODO b/drivers/staging/vc04_services/bcm2835-camera/TODO deleted file mode 100644 index 6c2b4ffe4996..000000000000 --- a/drivers/staging/vc04_services/bcm2835-camera/TODO +++ /dev/null @@ -1,17 +0,0 @@ -1) Support dma-buf memory management. - -In order to zero-copy import camera images into the 3D or display -pipelines, we need to export our buffers through dma-buf so that the -vc4 driver can import them. This may involve bringing in the VCSM -driver (which allows long-term management of regions of memory in the -space that the VPU reserved and Linux otherwise doesn't have access -to), or building some new protocol that allows VCSM-style management -of Linux's CMA memory. - -2) Avoid extra copies for padding of images. - -We expose V4L2_PIX_FMT_* formats that have a specified stride/height -padding in the V4L2 spec, but that padding doesn't match what the -hardware can do. If we exposed the native padding requirements -through the V4L2 "multiplanar" formats, the firmware would have one -less copy it needed to do. diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c deleted file mode 100644 index fa7ea4ca4c36..000000000000 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.c +++ /dev/null @@ -1,2011 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Broadcom BCM2835 V4L2 driver - * - * Copyright © 2013 Raspberry Pi (Trading) Ltd. - * - * Authors: Vincent Sanders @ Collabora - * Dave Stevenson @ Broadcom - * (now dave.stevenson@raspberrypi.org) - * Simon Mellor @ Broadcom - * Luke Diamand @ Broadcom - */ - -#include <linux/dma-mapping.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <media/videobuf2-vmalloc.h> -#include <media/videobuf2-dma-contig.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-fh.h> -#include <media/v4l2-event.h> -#include <media/v4l2-common.h> -#include <linux/delay.h> - -#include "../interface/vchiq_arm/vchiq_bus.h" -#include "../vchiq-mmal/mmal-common.h" -#include "../vchiq-mmal/mmal-encodings.h" -#include "../vchiq-mmal/mmal-vchiq.h" -#include "../vchiq-mmal/mmal-msg.h" -#include "../vchiq-mmal/mmal-parameters.h" -#include "bcm2835-camera.h" - -#define MIN_WIDTH 32 -#define MIN_HEIGHT 32 -#define MIN_BUFFER_SIZE (80 * 1024) - -#define MAX_VIDEO_MODE_WIDTH 1280 -#define MAX_VIDEO_MODE_HEIGHT 720 - -#define MAX_BCM2835_CAMERAS 2 - -int bcm2835_v4l2_debug; -module_param_named(debug, bcm2835_v4l2_debug, int, 0644); -MODULE_PARM_DESC(bcm2835_v4l2_debug, "Debug level 0-2"); - -#define UNSET (-1) -static int video_nr[] = {[0 ... (MAX_BCM2835_CAMERAS - 1)] = UNSET }; -module_param_array(video_nr, int, NULL, 0644); -MODULE_PARM_DESC(video_nr, "videoX start numbers, -1 is autodetect"); - -static int max_video_width = MAX_VIDEO_MODE_WIDTH; -static int max_video_height = MAX_VIDEO_MODE_HEIGHT; -module_param(max_video_width, int, 0644); -MODULE_PARM_DESC(max_video_width, "Threshold for video mode"); -module_param(max_video_height, int, 0644); -MODULE_PARM_DESC(max_video_height, "Threshold for video mode"); - -/* camera instance counter */ -static atomic_t camera_instance = ATOMIC_INIT(0); - -/* global device data array */ -static struct bcm2835_mmal_dev *gdev[MAX_BCM2835_CAMERAS]; - -#define FPS_MIN 1 -#define FPS_MAX 90 - -/* timeperframe: min/max and default */ -static const struct v4l2_fract - tpf_min = {.numerator = 1, .denominator = FPS_MAX}, - tpf_max = {.numerator = 1, .denominator = FPS_MIN}, - tpf_default = {.numerator = 1000, .denominator = 30000}; - -/* Container for MMAL and VB2 buffers*/ -struct vb2_mmal_buffer { - struct vb2_v4l2_buffer vb; - struct mmal_buffer mmal; -}; - -/* video formats */ -static struct mmal_fmt formats[] = { - { - .fourcc = V4L2_PIX_FMT_YUV420, - .mmal = MMAL_ENCODING_I420, - .depth = 12, - .mmal_component = COMP_CAMERA, - .ybbp = 1, - .remove_padding = true, - }, { - .fourcc = V4L2_PIX_FMT_YUYV, - .mmal = MMAL_ENCODING_YUYV, - .depth = 16, - .mmal_component = COMP_CAMERA, - .ybbp = 2, - .remove_padding = false, - }, { - .fourcc = V4L2_PIX_FMT_RGB24, - .mmal = MMAL_ENCODING_RGB24, - .depth = 24, - .mmal_component = COMP_CAMERA, - .ybbp = 3, - .remove_padding = false, - }, { - .fourcc = V4L2_PIX_FMT_JPEG, - .flags = V4L2_FMT_FLAG_COMPRESSED, - .mmal = MMAL_ENCODING_JPEG, - .depth = 8, - .mmal_component = COMP_IMAGE_ENCODE, - .ybbp = 0, - .remove_padding = false, - }, { - .fourcc = V4L2_PIX_FMT_H264, - .flags = V4L2_FMT_FLAG_COMPRESSED, - .mmal = MMAL_ENCODING_H264, - .depth = 8, - .mmal_component = COMP_VIDEO_ENCODE, - .ybbp = 0, - .remove_padding = false, - }, { - .fourcc = V4L2_PIX_FMT_MJPEG, - .flags = V4L2_FMT_FLAG_COMPRESSED, - .mmal = MMAL_ENCODING_MJPEG, - .depth = 8, - .mmal_component = COMP_VIDEO_ENCODE, - .ybbp = 0, - .remove_padding = false, - }, { - .fourcc = V4L2_PIX_FMT_YVYU, - .mmal = MMAL_ENCODING_YVYU, - .depth = 16, - .mmal_component = COMP_CAMERA, - .ybbp = 2, - .remove_padding = false, - }, { - .fourcc = V4L2_PIX_FMT_VYUY, - .mmal = MMAL_ENCODING_VYUY, - .depth = 16, - .mmal_component = COMP_CAMERA, - .ybbp = 2, - .remove_padding = false, - }, { - .fourcc = V4L2_PIX_FMT_UYVY, - .mmal = MMAL_ENCODING_UYVY, - .depth = 16, - .mmal_component = COMP_CAMERA, - .ybbp = 2, - .remove_padding = false, - }, { - .fourcc = V4L2_PIX_FMT_NV12, - .mmal = MMAL_ENCODING_NV12, - .depth = 12, - .mmal_component = COMP_CAMERA, - .ybbp = 1, - .remove_padding = true, - }, { - .fourcc = V4L2_PIX_FMT_BGR24, - .mmal = MMAL_ENCODING_BGR24, - .depth = 24, - .mmal_component = COMP_CAMERA, - .ybbp = 3, - .remove_padding = false, - }, { - .fourcc = V4L2_PIX_FMT_YVU420, - .mmal = MMAL_ENCODING_YV12, - .depth = 12, - .mmal_component = COMP_CAMERA, - .ybbp = 1, - .remove_padding = true, - }, { - .fourcc = V4L2_PIX_FMT_NV21, - .mmal = MMAL_ENCODING_NV21, - .depth = 12, - .mmal_component = COMP_CAMERA, - .ybbp = 1, - .remove_padding = true, - }, { - .fourcc = V4L2_PIX_FMT_BGR32, - .mmal = MMAL_ENCODING_BGRA, - .depth = 32, - .mmal_component = COMP_CAMERA, - .ybbp = 4, - .remove_padding = false, - }, -}; - -static struct mmal_fmt *get_format(struct v4l2_format *f) -{ - struct mmal_fmt *fmt; - unsigned int k; - - for (k = 0; k < ARRAY_SIZE(formats); k++) { - fmt = &formats[k]; - if (fmt->fourcc == f->fmt.pix.pixelformat) - return fmt; - } - - return NULL; -} - -/* ------------------------------------------------------------------ - * Videobuf queue operations - * ------------------------------------------------------------------ - */ - -static int queue_setup(struct vb2_queue *vq, - unsigned int *nbuffers, unsigned int *nplanes, - unsigned int sizes[], struct device *alloc_ctxs[]) -{ - struct bcm2835_mmal_dev *dev = vb2_get_drv_priv(vq); - unsigned long size; - - /* refuse queue setup if port is not configured */ - if (!dev->capture.port) { - v4l2_err(&dev->v4l2_dev, - "%s: capture port not configured\n", __func__); - return -EINVAL; - } - - /* Handle CREATE_BUFS situation - *nplanes != 0 */ - if (*nplanes) { - if (*nplanes != 1 || - sizes[0] < dev->capture.port->current_buffer.size) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s: dev:%p Invalid buffer request from CREATE_BUFS, size %u < %u, nplanes %u != 1\n", - __func__, dev, sizes[0], - dev->capture.port->current_buffer.size, - *nplanes); - return -EINVAL; - } else { - return 0; - } - } - - /* Handle REQBUFS situation */ - size = dev->capture.port->current_buffer.size; - if (size == 0) { - v4l2_err(&dev->v4l2_dev, - "%s: capture port buffer size is zero\n", __func__); - return -EINVAL; - } - - if (*nbuffers < dev->capture.port->minimum_buffer.num) - *nbuffers = dev->capture.port->minimum_buffer.num; - - dev->capture.port->current_buffer.num = *nbuffers; - - *nplanes = 1; - - sizes[0] = size; - - /* - * videobuf2-vmalloc allocator is context-less so no need to set - * alloc_ctxs array. - */ - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", - __func__, dev); - - return 0; -} - -static int buffer_init(struct vb2_buffer *vb) -{ - struct bcm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb); - struct vb2_mmal_buffer *buf = - container_of(vb2, struct vb2_mmal_buffer, vb); - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n", - __func__, dev, vb); - buf->mmal.buffer = vb2_plane_vaddr(&buf->vb.vb2_buf, 0); - buf->mmal.buffer_size = vb2_plane_size(&buf->vb.vb2_buf, 0); - - return mmal_vchi_buffer_init(dev->instance, &buf->mmal); -} - -static int buffer_prepare(struct vb2_buffer *vb) -{ - struct bcm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - unsigned long size; - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n", - __func__, dev, vb); - - if (!dev->capture.port || !dev->capture.fmt) - return -ENODEV; - - size = dev->capture.stride * dev->capture.height; - if (vb2_plane_size(vb, 0) < size) { - v4l2_err(&dev->v4l2_dev, - "%s data will not fit into plane (%lu < %lu)\n", - __func__, vb2_plane_size(vb, 0), size); - return -EINVAL; - } - - return 0; -} - -static void buffer_cleanup(struct vb2_buffer *vb) -{ - struct bcm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb); - struct vb2_mmal_buffer *buf = - container_of(vb2, struct vb2_mmal_buffer, vb); - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p, vb %p\n", - __func__, dev, vb); - - mmal_vchi_buffer_cleanup(&buf->mmal); -} - -static inline bool is_capturing(struct bcm2835_mmal_dev *dev) -{ - return dev->capture.camera_port == - &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE]; -} - -static void buffer_cb(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - int status, - struct mmal_buffer *mmal_buf) -{ - struct bcm2835_mmal_dev *dev = port->cb_ctx; - struct vb2_mmal_buffer *buf = - container_of(mmal_buf, struct vb2_mmal_buffer, mmal); - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s: status:%d, buf:%p, length:%lu, flags %u, pts %lld\n", - __func__, status, buf, mmal_buf->length, mmal_buf->mmal_flags, - mmal_buf->pts); - - if (status) { - /* error in transfer */ - if (buf) { - /* there was a buffer with the error so return it */ - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - } - return; - } - - if (mmal_buf->length == 0) { - /* stream ended */ - if (dev->capture.frame_count) { - /* empty buffer whilst capturing - expected to be an - * EOS, so grab another frame - */ - if (is_capturing(dev)) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Grab another frame"); - vchiq_mmal_port_parameter_set(instance, - dev->capture.camera_port, - MMAL_PARAMETER_CAPTURE, - &dev->capture.frame_count, - sizeof(dev->capture.frame_count)); - } - if (vchiq_mmal_submit_buffer(instance, port, - &buf->mmal)) - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Failed to return EOS buffer"); - } else { - /* stopping streaming. - * return buffer, and signal frame completion - */ - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - complete(&dev->capture.frame_cmplt); - } - return; - } - - if (!dev->capture.frame_count) { - /* signal frame completion */ - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); - complete(&dev->capture.frame_cmplt); - return; - } - - if (dev->capture.vc_start_timestamp != -1 && mmal_buf->pts) { - ktime_t timestamp; - s64 runtime_us = mmal_buf->pts - - dev->capture.vc_start_timestamp; - timestamp = ktime_add_us(dev->capture.kernel_start_ts, - runtime_us); - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Convert start time %llu and %llu with offset %llu to %llu\n", - ktime_to_ns(dev->capture.kernel_start_ts), - dev->capture.vc_start_timestamp, mmal_buf->pts, - ktime_to_ns(timestamp)); - buf->vb.vb2_buf.timestamp = ktime_to_ns(timestamp); - } else { - buf->vb.vb2_buf.timestamp = ktime_get_ns(); - } - buf->vb.sequence = dev->capture.sequence++; - buf->vb.field = V4L2_FIELD_NONE; - - vb2_set_plane_payload(&buf->vb.vb2_buf, 0, mmal_buf->length); - if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME) - buf->vb.flags |= V4L2_BUF_FLAG_KEYFRAME; - - vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE); - - if (mmal_buf->mmal_flags & MMAL_BUFFER_HEADER_FLAG_EOS && - is_capturing(dev)) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Grab another frame as buffer has EOS"); - vchiq_mmal_port_parameter_set(instance, - dev->capture.camera_port, - MMAL_PARAMETER_CAPTURE, - &dev->capture.frame_count, - sizeof(dev->capture.frame_count)); - } -} - -static int enable_camera(struct bcm2835_mmal_dev *dev) -{ - int ret; - - if (!dev->camera_use_count) { - ret = vchiq_mmal_port_parameter_set(dev->instance, - &dev->component[COMP_CAMERA]->control, - MMAL_PARAMETER_CAMERA_NUM, &dev->camera_num, - sizeof(dev->camera_num)); - if (ret < 0) { - v4l2_err(&dev->v4l2_dev, - "Failed setting camera num, ret %d\n", ret); - return -EINVAL; - } - - ret = vchiq_mmal_component_enable(dev->instance, - dev->component[COMP_CAMERA]); - if (ret < 0) { - v4l2_err(&dev->v4l2_dev, - "Failed enabling camera, ret %d\n", ret); - return -EINVAL; - } - } - dev->camera_use_count++; - v4l2_dbg(1, bcm2835_v4l2_debug, - &dev->v4l2_dev, "enabled camera (refcount %d)\n", - dev->camera_use_count); - return 0; -} - -static int disable_camera(struct bcm2835_mmal_dev *dev) -{ - int ret; - - if (!dev->camera_use_count) { - v4l2_err(&dev->v4l2_dev, - "Disabled the camera when already disabled\n"); - return -EINVAL; - } - dev->camera_use_count--; - if (!dev->camera_use_count) { - unsigned int i = 0xFFFFFFFF; - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Disabling camera\n"); - ret = vchiq_mmal_component_disable(dev->instance, - dev->component[COMP_CAMERA]); - if (ret < 0) { - v4l2_err(&dev->v4l2_dev, - "Failed disabling camera, ret %d\n", ret); - return -EINVAL; - } - vchiq_mmal_port_parameter_set(dev->instance, - &dev->component[COMP_CAMERA]->control, - MMAL_PARAMETER_CAMERA_NUM, - &i, - sizeof(i)); - } - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Camera refcount now %d\n", dev->camera_use_count); - return 0; -} - -static void buffer_queue(struct vb2_buffer *vb) -{ - struct bcm2835_mmal_dev *dev = vb2_get_drv_priv(vb->vb2_queue); - struct vb2_v4l2_buffer *vb2 = to_vb2_v4l2_buffer(vb); - struct vb2_mmal_buffer *buf = - container_of(vb2, struct vb2_mmal_buffer, vb); - int ret; - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s: dev:%p buf:%p, idx %u\n", - __func__, dev, buf, vb2->vb2_buf.index); - - ret = vchiq_mmal_submit_buffer(dev->instance, dev->capture.port, - &buf->mmal); - if (ret < 0) - v4l2_err(&dev->v4l2_dev, "%s: error submitting buffer\n", - __func__); -} - -static int start_streaming(struct vb2_queue *vq, unsigned int count) -{ - struct bcm2835_mmal_dev *dev = vb2_get_drv_priv(vq); - int ret; - u32 parameter_size; - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", - __func__, dev); - - /* ensure a format has actually been set */ - if (!dev->capture.port) - return -EINVAL; - - if (enable_camera(dev) < 0) { - v4l2_err(&dev->v4l2_dev, "Failed to enable camera\n"); - return -EINVAL; - } - - /*init_completion(&dev->capture.frame_cmplt); */ - - /* enable frame capture */ - dev->capture.frame_count = 1; - - /* reset sequence number */ - dev->capture.sequence = 0; - - /* if the preview is not already running, wait for a few frames for AGC - * to settle down. - */ - if (!dev->component[COMP_PREVIEW]->enabled) - msleep(300); - - /* enable the connection from camera to encoder (if applicable) */ - if (dev->capture.camera_port != dev->capture.port && - dev->capture.camera_port) { - ret = vchiq_mmal_port_enable(dev->instance, - dev->capture.camera_port, NULL); - if (ret) { - v4l2_err(&dev->v4l2_dev, - "Failed to enable encode tunnel - error %d\n", - ret); - return -1; - } - } - - /* Get VC timestamp at this point in time */ - parameter_size = sizeof(dev->capture.vc_start_timestamp); - if (vchiq_mmal_port_parameter_get(dev->instance, - dev->capture.camera_port, - MMAL_PARAMETER_SYSTEM_TIME, - &dev->capture.vc_start_timestamp, - ¶meter_size)) { - v4l2_err(&dev->v4l2_dev, - "Failed to get VC start time - update your VC f/w\n"); - - /* Flag to indicate just to rely on kernel timestamps */ - dev->capture.vc_start_timestamp = -1; - } else { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Start time %lld size %d\n", - dev->capture.vc_start_timestamp, parameter_size); - } - - dev->capture.kernel_start_ts = ktime_get(); - - /* enable the camera port */ - dev->capture.port->cb_ctx = dev; - ret = vchiq_mmal_port_enable(dev->instance, dev->capture.port, - buffer_cb); - if (ret) { - v4l2_err(&dev->v4l2_dev, - "Failed to enable capture port - error %d. Disabling camera port again\n", - ret); - - vchiq_mmal_port_disable(dev->instance, - dev->capture.camera_port); - if (disable_camera(dev) < 0) { - v4l2_err(&dev->v4l2_dev, "Failed to disable camera\n"); - return -EINVAL; - } - return -1; - } - - /* capture the first frame */ - vchiq_mmal_port_parameter_set(dev->instance, - dev->capture.camera_port, - MMAL_PARAMETER_CAPTURE, - &dev->capture.frame_count, - sizeof(dev->capture.frame_count)); - return 0; -} - -/* abort streaming and wait for last buffer */ -static void stop_streaming(struct vb2_queue *vq) -{ - int ret; - unsigned long time_left; - struct bcm2835_mmal_dev *dev = vb2_get_drv_priv(vq); - struct vchiq_mmal_port *port = dev->capture.port; - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "%s: dev:%p\n", - __func__, dev); - - init_completion(&dev->capture.frame_cmplt); - dev->capture.frame_count = 0; - - /* ensure a format has actually been set */ - if (!port) { - v4l2_err(&dev->v4l2_dev, - "no capture port - stream not started?\n"); - return; - } - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "stopping capturing\n"); - - /* stop capturing frames */ - vchiq_mmal_port_parameter_set(dev->instance, - dev->capture.camera_port, - MMAL_PARAMETER_CAPTURE, - &dev->capture.frame_count, - sizeof(dev->capture.frame_count)); - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "disabling connection\n"); - - /* disable the connection from camera to encoder */ - ret = vchiq_mmal_port_disable(dev->instance, dev->capture.camera_port); - if (!ret && dev->capture.camera_port != port) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "disabling port\n"); - ret = vchiq_mmal_port_disable(dev->instance, port); - } else if (dev->capture.camera_port != port) { - v4l2_err(&dev->v4l2_dev, "port_disable failed, error %d\n", - ret); - } - - /* wait for all buffers to be returned */ - while (atomic_read(&port->buffers_with_vpu)) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s: Waiting for buffers to be returned - %d outstanding\n", - __func__, atomic_read(&port->buffers_with_vpu)); - time_left = wait_for_completion_timeout(&dev->capture.frame_cmplt, - HZ); - if (time_left == 0) { - v4l2_err(&dev->v4l2_dev, "%s: Timeout waiting for buffers to be returned - %d outstanding\n", - __func__, - atomic_read(&port->buffers_with_vpu)); - break; - } - } - - if (disable_camera(dev) < 0) - v4l2_err(&dev->v4l2_dev, "Failed to disable camera\n"); -} - -static const struct vb2_ops bcm2835_mmal_video_qops = { - .queue_setup = queue_setup, - .buf_init = buffer_init, - .buf_prepare = buffer_prepare, - .buf_cleanup = buffer_cleanup, - .buf_queue = buffer_queue, - .start_streaming = start_streaming, - .stop_streaming = stop_streaming, -}; - -/* ------------------------------------------------------------------ - * IOCTL operations - * ------------------------------------------------------------------ - */ - -static int set_overlay_params(struct bcm2835_mmal_dev *dev, - struct vchiq_mmal_port *port) -{ - struct mmal_parameter_displayregion prev_config = { - .set = MMAL_DISPLAY_SET_LAYER | - MMAL_DISPLAY_SET_ALPHA | - MMAL_DISPLAY_SET_DEST_RECT | - MMAL_DISPLAY_SET_FULLSCREEN, - .layer = 2, - .alpha = dev->overlay.global_alpha, - .fullscreen = 0, - .dest_rect = { - .x = dev->overlay.w.left, - .y = dev->overlay.w.top, - .width = dev->overlay.w.width, - .height = dev->overlay.w.height, - }, - }; - return vchiq_mmal_port_parameter_set(dev->instance, port, - MMAL_PARAMETER_DISPLAYREGION, - &prev_config, sizeof(prev_config)); -} - -/* overlay ioctl */ -static int vidioc_enum_fmt_vid_overlay(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct mmal_fmt *fmt; - - if (f->index >= ARRAY_SIZE(formats)) - return -EINVAL; - - fmt = &formats[f->index]; - - f->pixelformat = fmt->fourcc; - - return 0; -} - -static int vidioc_g_fmt_vid_overlay(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct bcm2835_mmal_dev *dev = video_drvdata(file); - - f->fmt.win = dev->overlay; - - return 0; -} - -static int vidioc_try_fmt_vid_overlay(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct bcm2835_mmal_dev *dev = video_drvdata(file); - - f->fmt.win.field = V4L2_FIELD_NONE; - f->fmt.win.chromakey = 0; - f->fmt.win.clips = NULL; - f->fmt.win.clipcount = 0; - f->fmt.win.bitmap = NULL; - - v4l_bound_align_image(&f->fmt.win.w.width, MIN_WIDTH, dev->max_width, 1, - &f->fmt.win.w.height, MIN_HEIGHT, dev->max_height, - 1, 0); - v4l_bound_align_image(&f->fmt.win.w.left, MIN_WIDTH, dev->max_width, 1, - &f->fmt.win.w.top, MIN_HEIGHT, dev->max_height, - 1, 0); - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Overlay: Now w/h %dx%d l/t %dx%d\n", - f->fmt.win.w.width, f->fmt.win.w.height, - f->fmt.win.w.left, f->fmt.win.w.top); - - v4l2_dump_win_format(1, - bcm2835_v4l2_debug, - &dev->v4l2_dev, - &f->fmt.win, - __func__); - return 0; -} - -static int vidioc_s_fmt_vid_overlay(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct bcm2835_mmal_dev *dev = video_drvdata(file); - - vidioc_try_fmt_vid_overlay(file, priv, f); - - dev->overlay = f->fmt.win; - if (dev->component[COMP_PREVIEW]->enabled) { - set_overlay_params(dev, - &dev->component[COMP_PREVIEW]->input[0]); - } - - return 0; -} - -static int vidioc_overlay(struct file *file, void *f, unsigned int on) -{ - int ret; - struct bcm2835_mmal_dev *dev = video_drvdata(file); - struct vchiq_mmal_port *src; - struct vchiq_mmal_port *dst; - - if ((on && dev->component[COMP_PREVIEW]->enabled) || - (!on && !dev->component[COMP_PREVIEW]->enabled)) - return 0; /* already in requested state */ - - src = &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW]; - - if (!on) { - /* disconnect preview ports and disable component */ - ret = vchiq_mmal_port_disable(dev->instance, src); - if (!ret) - ret = vchiq_mmal_port_connect_tunnel(dev->instance, src, - NULL); - if (ret >= 0) - ret = vchiq_mmal_component_disable(dev->instance, - dev->component[COMP_PREVIEW]); - - disable_camera(dev); - return ret; - } - - /* set preview port format and connect it to output */ - dst = &dev->component[COMP_PREVIEW]->input[0]; - - ret = vchiq_mmal_port_set_format(dev->instance, src); - if (ret < 0) - return ret; - - ret = set_overlay_params(dev, dst); - if (ret < 0) - return ret; - - if (enable_camera(dev) < 0) - return -EINVAL; - - ret = vchiq_mmal_component_enable(dev->instance, - dev->component[COMP_PREVIEW]); - if (ret < 0) - return ret; - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, "connecting %p to %p\n", - src, dst); - ret = vchiq_mmal_port_connect_tunnel(dev->instance, src, dst); - if (ret) - return ret; - - return vchiq_mmal_port_enable(dev->instance, src, NULL); -} - -static int vidioc_g_fbuf(struct file *file, void *fh, - struct v4l2_framebuffer *a) -{ - /* The video overlay must stay within the framebuffer and can't be - * positioned independently. - */ - struct bcm2835_mmal_dev *dev = video_drvdata(file); - struct vchiq_mmal_port *preview_port = - &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW]; - - a->capability = V4L2_FBUF_CAP_EXTERNOVERLAY | - V4L2_FBUF_CAP_GLOBAL_ALPHA; - a->flags = V4L2_FBUF_FLAG_OVERLAY; - a->fmt.width = preview_port->es.video.width; - a->fmt.height = preview_port->es.video.height; - a->fmt.pixelformat = V4L2_PIX_FMT_YUV420; - a->fmt.bytesperline = preview_port->es.video.width; - a->fmt.sizeimage = (preview_port->es.video.width * - preview_port->es.video.height * 3) >> 1; - a->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M; - - return 0; -} - -/* input ioctls */ -static int vidioc_enum_input(struct file *file, void *priv, - struct v4l2_input *inp) -{ - /* only a single camera input */ - if (inp->index) - return -EINVAL; - - inp->type = V4L2_INPUT_TYPE_CAMERA; - snprintf((char *)inp->name, sizeof(inp->name), "Camera %u", inp->index); - return 0; -} - -static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) -{ - *i = 0; - return 0; -} - -static int vidioc_s_input(struct file *file, void *priv, unsigned int i) -{ - if (i) - return -EINVAL; - - return 0; -} - -/* capture ioctls */ -static int vidioc_querycap(struct file *file, void *priv, - struct v4l2_capability *cap) -{ - struct bcm2835_mmal_dev *dev = video_drvdata(file); - u32 major; - u32 minor; - - vchiq_mmal_version(dev->instance, &major, &minor); - - strscpy(cap->driver, "bcm2835 mmal", sizeof(cap->driver)); - snprintf((char *)cap->card, sizeof(cap->card), "mmal service %d.%d", major, minor); - - snprintf((char *)cap->bus_info, sizeof(cap->bus_info), "platform:%s", dev->v4l2_dev.name); - return 0; -} - -static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_fmtdesc *f) -{ - struct mmal_fmt *fmt; - - if (f->index >= ARRAY_SIZE(formats)) - return -EINVAL; - - fmt = &formats[f->index]; - - f->pixelformat = fmt->fourcc; - - return 0; -} - -static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct bcm2835_mmal_dev *dev = video_drvdata(file); - - f->fmt.pix.width = dev->capture.width; - f->fmt.pix.height = dev->capture.height; - f->fmt.pix.field = V4L2_FIELD_NONE; - f->fmt.pix.pixelformat = dev->capture.fmt->fourcc; - f->fmt.pix.bytesperline = dev->capture.stride; - f->fmt.pix.sizeimage = dev->capture.buffersize; - - if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_RGB24) - f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; - else if (dev->capture.fmt->fourcc == V4L2_PIX_FMT_JPEG) - f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; - else - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; - - v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix, - __func__); - return 0; -} - -static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - struct bcm2835_mmal_dev *dev = video_drvdata(file); - struct mmal_fmt *mfmt; - - mfmt = get_format(f); - if (!mfmt) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Fourcc format (0x%08x) unknown.\n", - f->fmt.pix.pixelformat); - f->fmt.pix.pixelformat = formats[0].fourcc; - mfmt = get_format(f); - } - - f->fmt.pix.field = V4L2_FIELD_NONE; - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Clipping/aligning %dx%d format %08X\n", - f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat); - - v4l_bound_align_image(&f->fmt.pix.width, MIN_WIDTH, dev->max_width, 1, - &f->fmt.pix.height, MIN_HEIGHT, dev->max_height, - 1, 0); - f->fmt.pix.bytesperline = f->fmt.pix.width * mfmt->ybbp; - if (!mfmt->remove_padding) { - if (mfmt->depth == 24) { - /* - * 24bpp is a pain as we can't use simple masking. - * Min stride is width aligned to 16, times 24bpp. - */ - f->fmt.pix.bytesperline = - ((f->fmt.pix.width + 15) & ~15) * 3; - } else { - /* - * GPU isn't removing padding, so stride is aligned to - * 32 - */ - int align_mask = ((32 * mfmt->depth) >> 3) - 1; - - f->fmt.pix.bytesperline = - (f->fmt.pix.bytesperline + align_mask) & - ~align_mask; - } - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Not removing padding, so bytes/line = %d\n", - f->fmt.pix.bytesperline); - } - - /* Image buffer has to be padded to allow for alignment, even though - * we sometimes then remove that padding before delivering the buffer. - */ - f->fmt.pix.sizeimage = ((f->fmt.pix.height + 15) & ~15) * - (((f->fmt.pix.width + 31) & ~31) * mfmt->depth) >> 3; - - if ((mfmt->flags & V4L2_FMT_FLAG_COMPRESSED) && - f->fmt.pix.sizeimage < MIN_BUFFER_SIZE) - f->fmt.pix.sizeimage = MIN_BUFFER_SIZE; - - if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) - f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB; - else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG) - f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG; - else - f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; - f->fmt.pix.priv = 0; - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Now %dx%d format %08X\n", - f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.pixelformat); - - v4l2_dump_pix_format(1, bcm2835_v4l2_debug, &dev->v4l2_dev, &f->fmt.pix, - __func__); - return 0; -} - -static int mmal_setup_video_component(struct bcm2835_mmal_dev *dev, - struct v4l2_format *f) -{ - bool overlay_enabled = !!dev->component[COMP_PREVIEW]->enabled; - struct vchiq_mmal_port *preview_port; - int ret; - - preview_port = &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW]; - - /* Preview and encode ports need to match on resolution */ - if (overlay_enabled) { - /* Need to disable the overlay before we can update - * the resolution - */ - ret = vchiq_mmal_port_disable(dev->instance, preview_port); - if (!ret) { - ret = vchiq_mmal_port_connect_tunnel(dev->instance, - preview_port, - NULL); - } - } - preview_port->es.video.width = f->fmt.pix.width; - preview_port->es.video.height = f->fmt.pix.height; - preview_port->es.video.crop.x = 0; - preview_port->es.video.crop.y = 0; - preview_port->es.video.crop.width = f->fmt.pix.width; - preview_port->es.video.crop.height = f->fmt.pix.height; - preview_port->es.video.frame_rate.numerator = - dev->capture.timeperframe.denominator; - preview_port->es.video.frame_rate.denominator = - dev->capture.timeperframe.numerator; - ret = vchiq_mmal_port_set_format(dev->instance, preview_port); - - if (overlay_enabled) { - ret = vchiq_mmal_port_connect_tunnel(dev->instance, - preview_port, - &dev->component[COMP_PREVIEW]->input[0]); - if (ret) - return ret; - - ret = vchiq_mmal_port_enable(dev->instance, preview_port, NULL); - } - - return ret; -} - -static int mmal_setup_encode_component(struct bcm2835_mmal_dev *dev, - struct v4l2_format *f, - struct vchiq_mmal_port *port, - struct vchiq_mmal_port *camera_port, - struct vchiq_mmal_component *component) -{ - struct mmal_fmt *mfmt = get_format(f); - int ret; - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "vid_cap - set up encode comp\n"); - - /* configure buffering */ - camera_port->current_buffer.size = camera_port->recommended_buffer.size; - camera_port->current_buffer.num = camera_port->recommended_buffer.num; - - ret = vchiq_mmal_port_connect_tunnel(dev->instance, camera_port, - &component->input[0]); - if (ret) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s failed to create connection\n", __func__); - /* ensure capture is not going to be tried */ - dev->capture.port = NULL; - return ret; - } - - port->es.video.width = f->fmt.pix.width; - port->es.video.height = f->fmt.pix.height; - port->es.video.crop.x = 0; - port->es.video.crop.y = 0; - port->es.video.crop.width = f->fmt.pix.width; - port->es.video.crop.height = f->fmt.pix.height; - port->es.video.frame_rate.numerator = - dev->capture.timeperframe.denominator; - port->es.video.frame_rate.denominator = - dev->capture.timeperframe.numerator; - - port->format.encoding = mfmt->mmal; - port->format.encoding_variant = 0; - /* Set any encoding specific parameters */ - switch (mfmt->mmal_component) { - case COMP_VIDEO_ENCODE: - port->format.bitrate = dev->capture.encode_bitrate; - break; - case COMP_IMAGE_ENCODE: - /* Could set EXIF parameters here */ - break; - default: - break; - } - - ret = vchiq_mmal_port_set_format(dev->instance, port); - if (ret) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s failed to set format %dx%d fmt %08X\n", - __func__, - f->fmt.pix.width, - f->fmt.pix.height, - f->fmt.pix.pixelformat); - return ret; - } - - ret = vchiq_mmal_component_enable(dev->instance, component); - if (ret) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s Failed to enable encode components\n", __func__); - return ret; - } - - /* configure buffering */ - port->current_buffer.num = 1; - port->current_buffer.size = f->fmt.pix.sizeimage; - if (port->format.encoding == MMAL_ENCODING_JPEG) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "JPG - buf size now %d was %d\n", - f->fmt.pix.sizeimage, - port->current_buffer.size); - port->current_buffer.size = - (f->fmt.pix.sizeimage < (100 << 10)) ? - (100 << 10) : f->fmt.pix.sizeimage; - } - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "vid_cap - cur_buf.size set to %d\n", f->fmt.pix.sizeimage); - port->current_buffer.alignment = 0; - - return 0; -} - -static int mmal_setup_components(struct bcm2835_mmal_dev *dev, - struct v4l2_format *f) -{ - int ret; - struct vchiq_mmal_port *port = NULL, *camera_port = NULL; - struct vchiq_mmal_component *encode_component = NULL; - struct mmal_fmt *mfmt = get_format(f); - bool remove_padding; - - if (!mfmt) - return -EINVAL; - - if (dev->capture.encode_component) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "vid_cap - disconnect previous tunnel\n"); - - /* Disconnect any previous connection */ - vchiq_mmal_port_connect_tunnel(dev->instance, - dev->capture.camera_port, NULL); - dev->capture.camera_port = NULL; - ret = vchiq_mmal_component_disable(dev->instance, - dev->capture.encode_component); - if (ret) - v4l2_err(&dev->v4l2_dev, - "Failed to disable encode component %d\n", - ret); - - dev->capture.encode_component = NULL; - } - /* format dependent port setup */ - switch (mfmt->mmal_component) { - case COMP_CAMERA: - /* Make a further decision on port based on resolution */ - if (f->fmt.pix.width <= max_video_width && - f->fmt.pix.height <= max_video_height) - camera_port = - &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO]; - else - camera_port = - &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE]; - port = camera_port; - break; - case COMP_IMAGE_ENCODE: - encode_component = dev->component[COMP_IMAGE_ENCODE]; - port = &dev->component[COMP_IMAGE_ENCODE]->output[0]; - camera_port = - &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE]; - break; - case COMP_VIDEO_ENCODE: - encode_component = dev->component[COMP_VIDEO_ENCODE]; - port = &dev->component[COMP_VIDEO_ENCODE]->output[0]; - camera_port = - &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO]; - break; - default: - break; - } - - if (!port) - return -EINVAL; - - if (encode_component) - camera_port->format.encoding = MMAL_ENCODING_OPAQUE; - else - camera_port->format.encoding = mfmt->mmal; - - if (dev->rgb_bgr_swapped) { - if (camera_port->format.encoding == MMAL_ENCODING_RGB24) - camera_port->format.encoding = MMAL_ENCODING_BGR24; - else if (camera_port->format.encoding == MMAL_ENCODING_BGR24) - camera_port->format.encoding = MMAL_ENCODING_RGB24; - } - - remove_padding = mfmt->remove_padding; - vchiq_mmal_port_parameter_set(dev->instance, camera_port, - MMAL_PARAMETER_NO_IMAGE_PADDING, - &remove_padding, sizeof(remove_padding)); - - camera_port->format.encoding_variant = 0; - camera_port->es.video.width = f->fmt.pix.width; - camera_port->es.video.height = f->fmt.pix.height; - camera_port->es.video.crop.x = 0; - camera_port->es.video.crop.y = 0; - camera_port->es.video.crop.width = f->fmt.pix.width; - camera_port->es.video.crop.height = f->fmt.pix.height; - camera_port->es.video.frame_rate.numerator = 0; - camera_port->es.video.frame_rate.denominator = 1; - camera_port->es.video.color_space = MMAL_COLOR_SPACE_JPEG_JFIF; - - ret = vchiq_mmal_port_set_format(dev->instance, camera_port); - - if (!ret && - camera_port == - &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO]) { - ret = mmal_setup_video_component(dev, f); - } - - if (ret) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s failed to set format %dx%d %08X\n", __func__, - f->fmt.pix.width, f->fmt.pix.height, - f->fmt.pix.pixelformat); - /* ensure capture is not going to be tried */ - dev->capture.port = NULL; - return ret; - } - - if (encode_component) { - ret = mmal_setup_encode_component(dev, f, port, - camera_port, - encode_component); - - if (ret) - return ret; - } else { - /* configure buffering */ - camera_port->current_buffer.num = 1; - camera_port->current_buffer.size = f->fmt.pix.sizeimage; - camera_port->current_buffer.alignment = 0; - } - - dev->capture.fmt = mfmt; - dev->capture.stride = f->fmt.pix.bytesperline; - dev->capture.width = camera_port->es.video.crop.width; - dev->capture.height = camera_port->es.video.crop.height; - dev->capture.buffersize = port->current_buffer.size; - - /* select port for capture */ - dev->capture.port = port; - dev->capture.camera_port = camera_port; - dev->capture.encode_component = encode_component; - v4l2_dbg(1, bcm2835_v4l2_debug, - &dev->v4l2_dev, - "Set dev->capture.fmt %08X, %dx%d, stride %d, size %d", - port->format.encoding, - dev->capture.width, dev->capture.height, - dev->capture.stride, dev->capture.buffersize); - - /* todo: Need to convert the vchiq/mmal error into a v4l2 error. */ - return ret; -} - -static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, - struct v4l2_format *f) -{ - int ret; - struct bcm2835_mmal_dev *dev = video_drvdata(file); - struct mmal_fmt *mfmt; - - /* try the format to set valid parameters */ - ret = vidioc_try_fmt_vid_cap(file, priv, f); - if (ret) { - v4l2_err(&dev->v4l2_dev, - "vid_cap - vidioc_try_fmt_vid_cap failed\n"); - return ret; - } - - /* if a capture is running refuse to set format */ - if (vb2_is_busy(&dev->capture.vb_vidq)) { - v4l2_info(&dev->v4l2_dev, "%s device busy\n", __func__); - return -EBUSY; - } - - /* If the format is unsupported v4l2 says we should switch to - * a supported one and not return an error. - */ - mfmt = get_format(f); - if (!mfmt) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Fourcc format (0x%08x) unknown.\n", - f->fmt.pix.pixelformat); - f->fmt.pix.pixelformat = formats[0].fourcc; - mfmt = get_format(f); - } - - ret = mmal_setup_components(dev, f); - if (ret) { - v4l2_err(&dev->v4l2_dev, - "%s: failed to setup mmal components: %d\n", - __func__, ret); - ret = -EINVAL; - } - - return ret; -} - -static int vidioc_enum_framesizes(struct file *file, void *fh, - struct v4l2_frmsizeenum *fsize) -{ - struct bcm2835_mmal_dev *dev = video_drvdata(file); - static const struct v4l2_frmsize_stepwise sizes = { - MIN_WIDTH, 0, 2, - MIN_HEIGHT, 0, 2 - }; - int i; - - if (fsize->index) - return -EINVAL; - for (i = 0; i < ARRAY_SIZE(formats); i++) - if (formats[i].fourcc == fsize->pixel_format) - break; - if (i == ARRAY_SIZE(formats)) - return -EINVAL; - fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; - fsize->stepwise = sizes; - fsize->stepwise.max_width = dev->max_width; - fsize->stepwise.max_height = dev->max_height; - return 0; -} - -/* timeperframe is arbitrary and continuous */ -static int vidioc_enum_frameintervals(struct file *file, void *priv, - struct v4l2_frmivalenum *fival) -{ - struct bcm2835_mmal_dev *dev = video_drvdata(file); - int i; - - if (fival->index) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(formats); i++) - if (formats[i].fourcc == fival->pixel_format) - break; - if (i == ARRAY_SIZE(formats)) - return -EINVAL; - - /* regarding width & height - we support any within range */ - if (fival->width < MIN_WIDTH || fival->width > dev->max_width || - fival->height < MIN_HEIGHT || fival->height > dev->max_height) - return -EINVAL; - - fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS; - - /* fill in stepwise (step=1.0 is required by V4L2 spec) */ - fival->stepwise.min = tpf_min; - fival->stepwise.max = tpf_max; - fival->stepwise.step = (struct v4l2_fract) {1, 1}; - - return 0; -} - -static int vidioc_g_parm(struct file *file, void *priv, - struct v4l2_streamparm *parm) -{ - struct bcm2835_mmal_dev *dev = video_drvdata(file); - - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; - parm->parm.capture.timeperframe = dev->capture.timeperframe; - parm->parm.capture.readbuffers = 1; - return 0; -} - -static int vidioc_s_parm(struct file *file, void *priv, - struct v4l2_streamparm *parm) -{ - struct bcm2835_mmal_dev *dev = video_drvdata(file); - struct v4l2_fract tpf; - - if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) - return -EINVAL; - - tpf = parm->parm.capture.timeperframe; - - /* tpf: {*, 0} resets timing; clip to [min, max]*/ - tpf = tpf.denominator ? tpf : tpf_default; - tpf = V4L2_FRACT_COMPARE(tpf, <, tpf_min) ? tpf_min : tpf; - tpf = V4L2_FRACT_COMPARE(tpf, >, tpf_max) ? tpf_max : tpf; - - dev->capture.timeperframe = tpf; - parm->parm.capture.timeperframe = tpf; - parm->parm.capture.readbuffers = 1; - parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME; - - set_framerate_params(dev); - - return 0; -} - -static const struct v4l2_ioctl_ops camera0_ioctl_ops = { - /* overlay */ - .vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_overlay, - .vidioc_g_fmt_vid_overlay = vidioc_g_fmt_vid_overlay, - .vidioc_try_fmt_vid_overlay = vidioc_try_fmt_vid_overlay, - .vidioc_s_fmt_vid_overlay = vidioc_s_fmt_vid_overlay, - .vidioc_overlay = vidioc_overlay, - .vidioc_g_fbuf = vidioc_g_fbuf, - - /* inputs */ - .vidioc_enum_input = vidioc_enum_input, - .vidioc_g_input = vidioc_g_input, - .vidioc_s_input = vidioc_s_input, - - /* capture */ - .vidioc_querycap = vidioc_querycap, - .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, - .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, - .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, - .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, - - /* buffer management */ - .vidioc_reqbufs = vb2_ioctl_reqbufs, - .vidioc_create_bufs = vb2_ioctl_create_bufs, - .vidioc_prepare_buf = vb2_ioctl_prepare_buf, - .vidioc_querybuf = vb2_ioctl_querybuf, - .vidioc_qbuf = vb2_ioctl_qbuf, - .vidioc_dqbuf = vb2_ioctl_dqbuf, - .vidioc_enum_framesizes = vidioc_enum_framesizes, - .vidioc_enum_frameintervals = vidioc_enum_frameintervals, - .vidioc_g_parm = vidioc_g_parm, - .vidioc_s_parm = vidioc_s_parm, - .vidioc_streamon = vb2_ioctl_streamon, - .vidioc_streamoff = vb2_ioctl_streamoff, - - .vidioc_log_status = v4l2_ctrl_log_status, - .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, - .vidioc_unsubscribe_event = v4l2_event_unsubscribe, -}; - -/* ------------------------------------------------------------------ - * Driver init/finalise - * ------------------------------------------------------------------ - */ - -static const struct v4l2_file_operations camera0_fops = { - .owner = THIS_MODULE, - .open = v4l2_fh_open, - .release = vb2_fop_release, - .read = vb2_fop_read, - .poll = vb2_fop_poll, - .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ - .mmap = vb2_fop_mmap, -}; - -static const struct video_device vdev_template = { - .name = "camera0", - .fops = &camera0_fops, - .ioctl_ops = &camera0_ioctl_ops, - .release = video_device_release_empty, - .device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | - V4L2_CAP_STREAMING | V4L2_CAP_READWRITE, -}; - -/* Returns the number of cameras, and also the max resolution supported - * by those cameras. - */ -static int get_num_cameras(struct vchiq_mmal_instance *instance, - unsigned int resolutions[][2], int num_resolutions) -{ - int ret; - struct vchiq_mmal_component *cam_info_component; - struct mmal_parameter_camera_info cam_info = {0}; - u32 param_size = sizeof(cam_info); - int i; - - /* create a camera_info component */ - ret = vchiq_mmal_component_init(instance, "camera_info", - &cam_info_component); - if (ret < 0) - /* Unusual failure - let's guess one camera. */ - return 1; - - if (vchiq_mmal_port_parameter_get(instance, - &cam_info_component->control, - MMAL_PARAMETER_CAMERA_INFO, - &cam_info, - ¶m_size)) { - pr_info("Failed to get camera info\n"); - } - for (i = 0; - i < min_t(unsigned int, cam_info.num_cameras, num_resolutions); - i++) { - resolutions[i][0] = cam_info.cameras[i].max_width; - resolutions[i][1] = cam_info.cameras[i].max_height; - } - - vchiq_mmal_component_finalise(instance, - cam_info_component); - - return cam_info.num_cameras; -} - -static int set_camera_parameters(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *camera, - struct bcm2835_mmal_dev *dev) -{ - struct mmal_parameter_camera_config cam_config = { - .max_stills_w = dev->max_width, - .max_stills_h = dev->max_height, - .stills_yuv422 = 1, - .one_shot_stills = 1, - .max_preview_video_w = (max_video_width > 1920) ? - max_video_width : 1920, - .max_preview_video_h = (max_video_height > 1088) ? - max_video_height : 1088, - .num_preview_video_frames = 3, - .stills_capture_circular_buffer_height = 0, - .fast_preview_resume = 0, - .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RAW_STC - }; - - return vchiq_mmal_port_parameter_set(instance, &camera->control, - MMAL_PARAMETER_CAMERA_CONFIG, - &cam_config, sizeof(cam_config)); -} - -#define MAX_SUPPORTED_ENCODINGS 20 - -/* MMAL instance and component init */ -static int mmal_init(struct bcm2835_mmal_dev *dev) -{ - int ret; - struct mmal_es_format_local *format; - u32 supported_encodings[MAX_SUPPORTED_ENCODINGS]; - u32 param_size; - struct vchiq_mmal_component *camera; - - ret = vchiq_mmal_init(dev->v4l2_dev.dev, &dev->instance); - if (ret < 0) { - v4l2_err(&dev->v4l2_dev, "%s: vchiq mmal init failed %d\n", - __func__, ret); - return ret; - } - - /* get the camera component ready */ - ret = vchiq_mmal_component_init(dev->instance, "ril.camera", - &dev->component[COMP_CAMERA]); - if (ret < 0) - goto unreg_mmal; - - camera = dev->component[COMP_CAMERA]; - if (camera->outputs < CAM_PORT_COUNT) { - v4l2_err(&dev->v4l2_dev, "%s: too few camera outputs %d needed %d\n", - __func__, camera->outputs, CAM_PORT_COUNT); - ret = -EINVAL; - goto unreg_camera; - } - - ret = set_camera_parameters(dev->instance, - camera, - dev); - if (ret < 0) { - v4l2_err(&dev->v4l2_dev, "%s: unable to set camera parameters: %d\n", - __func__, ret); - goto unreg_camera; - } - - /* There was an error in the firmware that meant the camera component - * produced BGR instead of RGB. - * This is now fixed, but in order to support the old firmwares, we - * have to check. - */ - dev->rgb_bgr_swapped = true; - param_size = sizeof(supported_encodings); - ret = vchiq_mmal_port_parameter_get(dev->instance, - &camera->output[CAM_PORT_CAPTURE], - MMAL_PARAMETER_SUPPORTED_ENCODINGS, - &supported_encodings, - ¶m_size); - if (ret == 0) { - int i; - - for (i = 0; i < param_size / sizeof(u32); i++) { - if (supported_encodings[i] == MMAL_ENCODING_BGR24) { - /* Found BGR24 first - old firmware. */ - break; - } - if (supported_encodings[i] == MMAL_ENCODING_RGB24) { - /* Found RGB24 first - * new firmware, so use RGB24. - */ - dev->rgb_bgr_swapped = false; - break; - } - } - } - format = &camera->output[CAM_PORT_PREVIEW].format; - - format->encoding = MMAL_ENCODING_OPAQUE; - format->encoding_variant = MMAL_ENCODING_I420; - - format->es->video.width = 1024; - format->es->video.height = 768; - format->es->video.crop.x = 0; - format->es->video.crop.y = 0; - format->es->video.crop.width = 1024; - format->es->video.crop.height = 768; - format->es->video.frame_rate.numerator = 0; /* Rely on fps_range */ - format->es->video.frame_rate.denominator = 1; - - format = &camera->output[CAM_PORT_VIDEO].format; - - format->encoding = MMAL_ENCODING_OPAQUE; - format->encoding_variant = MMAL_ENCODING_I420; - - format->es->video.width = 1024; - format->es->video.height = 768; - format->es->video.crop.x = 0; - format->es->video.crop.y = 0; - format->es->video.crop.width = 1024; - format->es->video.crop.height = 768; - format->es->video.frame_rate.numerator = 0; /* Rely on fps_range */ - format->es->video.frame_rate.denominator = 1; - - format = &camera->output[CAM_PORT_CAPTURE].format; - - format->encoding = MMAL_ENCODING_OPAQUE; - - format->es->video.width = 2592; - format->es->video.height = 1944; - format->es->video.crop.x = 0; - format->es->video.crop.y = 0; - format->es->video.crop.width = 2592; - format->es->video.crop.height = 1944; - format->es->video.frame_rate.numerator = 0; /* Rely on fps_range */ - format->es->video.frame_rate.denominator = 1; - - dev->capture.width = format->es->video.width; - dev->capture.height = format->es->video.height; - dev->capture.fmt = &formats[0]; - dev->capture.encode_component = NULL; - dev->capture.timeperframe = tpf_default; - dev->capture.enc_profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH; - dev->capture.enc_level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0; - - /* get the preview component ready */ - ret = vchiq_mmal_component_init(dev->instance, "ril.video_render", - &dev->component[COMP_PREVIEW]); - if (ret < 0) - goto unreg_camera; - - if (dev->component[COMP_PREVIEW]->inputs < 1) { - ret = -EINVAL; - v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n", - __func__, dev->component[COMP_PREVIEW]->inputs, 1); - goto unreg_preview; - } - - /* get the image encoder component ready */ - ret = vchiq_mmal_component_init(dev->instance, "ril.image_encode", - &dev->component[COMP_IMAGE_ENCODE]); - if (ret < 0) - goto unreg_preview; - - if (dev->component[COMP_IMAGE_ENCODE]->inputs < 1) { - ret = -EINVAL; - v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n", - __func__, dev->component[COMP_IMAGE_ENCODE]->inputs, - 1); - goto unreg_image_encoder; - } - - /* get the video encoder component ready */ - ret = vchiq_mmal_component_init(dev->instance, "ril.video_encode", - &dev->component[COMP_VIDEO_ENCODE]); - if (ret < 0) - goto unreg_image_encoder; - - if (dev->component[COMP_VIDEO_ENCODE]->inputs < 1) { - ret = -EINVAL; - v4l2_err(&dev->v4l2_dev, "%s: too few input ports %d needed %d\n", - __func__, dev->component[COMP_VIDEO_ENCODE]->inputs, - 1); - goto unreg_vid_encoder; - } - - { - struct vchiq_mmal_port *encoder_port = - &dev->component[COMP_VIDEO_ENCODE]->output[0]; - encoder_port->format.encoding = MMAL_ENCODING_H264; - ret = vchiq_mmal_port_set_format(dev->instance, - encoder_port); - } - - { - unsigned int enable = 1; - - vchiq_mmal_port_parameter_set(dev->instance, - &dev->component[COMP_VIDEO_ENCODE]->control, - MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, - &enable, - sizeof(enable)); - - vchiq_mmal_port_parameter_set(dev->instance, - &dev->component[COMP_VIDEO_ENCODE]->control, - MMAL_PARAMETER_MINIMISE_FRAGMENTATION, - &enable, - sizeof(enable)); - } - ret = bcm2835_mmal_set_all_camera_controls(dev); - if (ret < 0) { - v4l2_err(&dev->v4l2_dev, "%s: failed to set all camera controls: %d\n", - __func__, ret); - goto unreg_vid_encoder; - } - - return 0; - -unreg_vid_encoder: - pr_err("Cleanup: Destroy video encoder\n"); - vchiq_mmal_component_finalise(dev->instance, - dev->component[COMP_VIDEO_ENCODE]); - -unreg_image_encoder: - pr_err("Cleanup: Destroy image encoder\n"); - vchiq_mmal_component_finalise(dev->instance, - dev->component[COMP_IMAGE_ENCODE]); - -unreg_preview: - pr_err("Cleanup: Destroy video render\n"); - vchiq_mmal_component_finalise(dev->instance, - dev->component[COMP_PREVIEW]); - -unreg_camera: - pr_err("Cleanup: Destroy camera\n"); - vchiq_mmal_component_finalise(dev->instance, - dev->component[COMP_CAMERA]); - -unreg_mmal: - vchiq_mmal_finalise(dev->instance); - return ret; -} - -static int bcm2835_mmal_init_device(struct bcm2835_mmal_dev *dev, struct video_device *vfd) -{ - int ret; - - *vfd = vdev_template; - - vfd->v4l2_dev = &dev->v4l2_dev; - - vfd->lock = &dev->mutex; - - vfd->queue = &dev->capture.vb_vidq; - - /* video device needs to be able to access instance data */ - video_set_drvdata(vfd, dev); - - ret = video_register_device(vfd, VFL_TYPE_VIDEO, - video_nr[dev->camera_num]); - if (ret < 0) - return ret; - - v4l2_info(vfd->v4l2_dev, - "V4L2 device registered as %s - stills mode > %dx%d\n", - video_device_node_name(vfd), - max_video_width, max_video_height); - - return 0; -} - -static void bcm2835_cleanup_instance(struct bcm2835_mmal_dev *dev) -{ - if (!dev) - return; - - v4l2_info(&dev->v4l2_dev, "unregistering %s\n", - video_device_node_name(&dev->vdev)); - - video_unregister_device(&dev->vdev); - - if (dev->capture.encode_component) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "mmal_exit - disconnect tunnel\n"); - vchiq_mmal_port_connect_tunnel(dev->instance, - dev->capture.camera_port, NULL); - vchiq_mmal_component_disable(dev->instance, - dev->capture.encode_component); - } - vchiq_mmal_component_disable(dev->instance, - dev->component[COMP_CAMERA]); - - vchiq_mmal_component_finalise(dev->instance, - dev->component[COMP_VIDEO_ENCODE]); - - vchiq_mmal_component_finalise(dev->instance, - dev->component[COMP_IMAGE_ENCODE]); - - vchiq_mmal_component_finalise(dev->instance, - dev->component[COMP_PREVIEW]); - - vchiq_mmal_component_finalise(dev->instance, - dev->component[COMP_CAMERA]); - - v4l2_ctrl_handler_free(&dev->ctrl_handler); - - v4l2_device_unregister(&dev->v4l2_dev); - - kfree(dev); -} - -static struct v4l2_format default_v4l2_format = { - .fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG, - .fmt.pix.width = 1024, - .fmt.pix.bytesperline = 0, - .fmt.pix.height = 768, - .fmt.pix.sizeimage = 1024 * 768, -}; - -static int bcm2835_mmal_probe(struct vchiq_device *device) -{ - int ret; - struct bcm2835_mmal_dev *dev; - struct vb2_queue *q; - int camera; - unsigned int num_cameras; - struct vchiq_mmal_instance *instance; - unsigned int resolutions[MAX_BCM2835_CAMERAS][2]; - int i; - - ret = dma_set_mask_and_coherent(&device->dev, DMA_BIT_MASK(32)); - if (ret) { - dev_err(&device->dev, "dma_set_mask_and_coherent failed: %d\n", ret); - return ret; - } - - ret = vchiq_mmal_init(&device->dev, &instance); - if (ret < 0) - return ret; - - num_cameras = get_num_cameras(instance, - resolutions, - MAX_BCM2835_CAMERAS); - - if (num_cameras < 1) { - ret = -ENODEV; - goto cleanup_mmal; - } - - if (num_cameras > MAX_BCM2835_CAMERAS) - num_cameras = MAX_BCM2835_CAMERAS; - - for (camera = 0; camera < num_cameras; camera++) { - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - ret = -ENOMEM; - goto cleanup_gdev; - } - - /* v4l2 core mutex used to protect all fops and v4l2 ioctls. */ - mutex_init(&dev->mutex); - dev->max_width = resolutions[camera][0]; - dev->max_height = resolutions[camera][1]; - - /* setup device defaults */ - dev->overlay.w.left = 150; - dev->overlay.w.top = 50; - dev->overlay.w.width = 1024; - dev->overlay.w.height = 768; - dev->overlay.clipcount = 0; - dev->overlay.field = V4L2_FIELD_NONE; - dev->overlay.global_alpha = 255; - - dev->capture.fmt = &formats[3]; /* JPEG */ - - /* v4l device registration */ - dev->camera_num = v4l2_device_set_name(&dev->v4l2_dev, KBUILD_MODNAME, - &camera_instance); - ret = v4l2_device_register(NULL, &dev->v4l2_dev); - if (ret) { - dev_err(&device->dev, "%s: could not register V4L2 device: %d\n", - __func__, ret); - goto free_dev; - } - dev->v4l2_dev.dev = &device->dev; - - /* setup v4l controls */ - ret = bcm2835_mmal_init_controls(dev, &dev->ctrl_handler); - if (ret < 0) { - v4l2_err(&dev->v4l2_dev, "%s: could not init controls: %d\n", - __func__, ret); - goto unreg_dev; - } - dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler; - - /* mmal init */ - dev->instance = instance; - ret = mmal_init(dev); - if (ret < 0) { - v4l2_err(&dev->v4l2_dev, "%s: mmal init failed: %d\n", - __func__, ret); - goto unreg_dev; - } - /* initialize queue */ - q = &dev->capture.vb_vidq; - memset(q, 0, sizeof(*q)); - q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ; - q->drv_priv = dev; - q->buf_struct_size = sizeof(struct vb2_mmal_buffer); - q->ops = &bcm2835_mmal_video_qops; - q->mem_ops = &vb2_vmalloc_memops; - q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->lock = &dev->mutex; - ret = vb2_queue_init(q); - if (ret < 0) - goto unreg_dev; - - /* initialise video devices */ - ret = bcm2835_mmal_init_device(dev, &dev->vdev); - if (ret < 0) { - v4l2_err(&dev->v4l2_dev, "%s: could not init device: %d\n", - __func__, ret); - goto unreg_dev; - } - - /* Really want to call vidioc_s_fmt_vid_cap with the default - * format, but currently the APIs don't join up. - */ - ret = mmal_setup_components(dev, &default_v4l2_format); - if (ret < 0) { - v4l2_err(&dev->v4l2_dev, "%s: could not setup components: %d\n", - __func__, ret); - goto unreg_dev; - } - - v4l2_info(&dev->v4l2_dev, "Broadcom 2835 MMAL video capture loaded.\n"); - - gdev[camera] = dev; - } - return 0; - -unreg_dev: - v4l2_ctrl_handler_free(&dev->ctrl_handler); - v4l2_device_unregister(&dev->v4l2_dev); - -free_dev: - kfree(dev); - -cleanup_gdev: - for (i = 0; i < camera; i++) { - bcm2835_cleanup_instance(gdev[i]); - gdev[i] = NULL; - } - -cleanup_mmal: - vchiq_mmal_finalise(instance); - - return ret; -} - -static void bcm2835_mmal_remove(struct vchiq_device *device) -{ - int camera; - struct vchiq_mmal_instance *instance = gdev[0]->instance; - - for (camera = 0; camera < MAX_BCM2835_CAMERAS; camera++) { - bcm2835_cleanup_instance(gdev[camera]); - gdev[camera] = NULL; - } - vchiq_mmal_finalise(instance); -} - -static const struct vchiq_device_id device_id_table[] = { - { .name = "bcm2835-camera" }, - {} -}; -MODULE_DEVICE_TABLE(vchiq, device_id_table); - -static struct vchiq_driver bcm2835_camera_driver = { - .probe = bcm2835_mmal_probe, - .remove = bcm2835_mmal_remove, - .id_table = device_id_table, - .driver = { - .name = "bcm2835-camera", - }, -}; - -module_vchiq_driver(bcm2835_camera_driver) - -MODULE_DESCRIPTION("Broadcom 2835 MMAL video capture"); -MODULE_AUTHOR("Vincent Sanders"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h b/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h deleted file mode 100644 index 0f0c6f7a3764..000000000000 --- a/drivers/staging/vc04_services/bcm2835-camera/bcm2835-camera.h +++ /dev/null @@ -1,142 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 V4L2 driver - * - * Copyright © 2013 Raspberry Pi (Trading) Ltd. - * - * Authors: Vincent Sanders @ Collabora - * Dave Stevenson @ Broadcom - * (now dave.stevenson@raspberrypi.org) - * Simon Mellor @ Broadcom - * Luke Diamand @ Broadcom - * - * core driver device - */ - -#define V4L2_CTRL_COUNT 29 /* number of v4l controls */ - -enum { - COMP_CAMERA = 0, - COMP_PREVIEW, - COMP_IMAGE_ENCODE, - COMP_VIDEO_ENCODE, - COMP_COUNT -}; - -enum { - CAM_PORT_PREVIEW = 0, - CAM_PORT_VIDEO, - CAM_PORT_CAPTURE, - CAM_PORT_COUNT -}; - -extern int bcm2835_v4l2_debug; - -struct bcm2835_mmal_dev { - /* v4l2 devices */ - struct v4l2_device v4l2_dev; - struct video_device vdev; - struct mutex mutex; - - /* controls */ - struct v4l2_ctrl_handler ctrl_handler; - struct v4l2_ctrl *ctrls[V4L2_CTRL_COUNT]; - enum v4l2_scene_mode scene_mode; - struct mmal_colourfx colourfx; - int hflip; - int vflip; - int red_gain; - int blue_gain; - enum mmal_parameter_exposuremode exposure_mode_user; - enum v4l2_exposure_auto_type exposure_mode_v4l2_user; - /* active exposure mode may differ if selected via a scene mode */ - enum mmal_parameter_exposuremode exposure_mode_active; - enum mmal_parameter_exposuremeteringmode metering_mode; - unsigned int manual_shutter_speed; - bool exp_auto_priority; - bool manual_iso_enabled; - u32 iso; - - /* allocated mmal instance and components */ - struct vchiq_mmal_instance *instance; - struct vchiq_mmal_component *component[COMP_COUNT]; - int camera_use_count; - - struct v4l2_window overlay; - - struct { - unsigned int width; /* width */ - unsigned int height; /* height */ - unsigned int stride; /* stride */ - unsigned int buffersize; /* buffer size with padding */ - struct mmal_fmt *fmt; - struct v4l2_fract timeperframe; - - /* H264 encode bitrate */ - int encode_bitrate; - /* H264 bitrate mode. CBR/VBR */ - int encode_bitrate_mode; - /* H264 profile */ - enum v4l2_mpeg_video_h264_profile enc_profile; - /* H264 level */ - enum v4l2_mpeg_video_h264_level enc_level; - /* JPEG Q-factor */ - int q_factor; - - struct vb2_queue vb_vidq; - - /* VC start timestamp for streaming */ - s64 vc_start_timestamp; - /* Kernel start timestamp for streaming */ - ktime_t kernel_start_ts; - /* Sequence number of last buffer */ - u32 sequence; - - struct vchiq_mmal_port *port; /* port being used for capture */ - /* camera port being used for capture */ - struct vchiq_mmal_port *camera_port; - /* component being used for encode */ - struct vchiq_mmal_component *encode_component; - /* number of frames remaining which driver should capture */ - unsigned int frame_count; - /* last frame completion */ - struct completion frame_cmplt; - - } capture; - - unsigned int camera_num; - unsigned int max_width; - unsigned int max_height; - unsigned int rgb_bgr_swapped; -}; - -int bcm2835_mmal_init_controls(struct bcm2835_mmal_dev *dev, struct v4l2_ctrl_handler *hdl); - -int bcm2835_mmal_set_all_camera_controls(struct bcm2835_mmal_dev *dev); -int set_framerate_params(struct bcm2835_mmal_dev *dev); - -/* Debug helpers */ - -#define v4l2_dump_pix_format(level, debug, dev, pix_fmt, desc) \ -{ \ - v4l2_dbg(level, debug, dev, \ -"%s: w %u h %u field %u pfmt 0x%x bpl %u sz_img %u colorspace 0x%x priv %u\n", \ - desc, \ - (pix_fmt)->width, (pix_fmt)->height, (pix_fmt)->field, \ - (pix_fmt)->pixelformat, (pix_fmt)->bytesperline, \ - (pix_fmt)->sizeimage, (pix_fmt)->colorspace, (pix_fmt)->priv); \ -} - -#define v4l2_dump_win_format(level, debug, dev, win_fmt, desc) \ -{ \ - v4l2_dbg(level, debug, dev, \ -"%s: w %u h %u l %u t %u field %u chromakey %06X clip %p " \ -"clipcount %u bitmap %p\n", \ - desc, \ - (win_fmt)->w.width, (win_fmt)->w.height, \ - (win_fmt)->w.left, (win_fmt)->w.top, \ - (win_fmt)->field, \ - (win_fmt)->chromakey, \ - (win_fmt)->clips, (win_fmt)->clipcount, \ - (win_fmt)->bitmap); \ -} diff --git a/drivers/staging/vc04_services/bcm2835-camera/controls.c b/drivers/staging/vc04_services/bcm2835-camera/controls.c deleted file mode 100644 index e670226f1edf..000000000000 --- a/drivers/staging/vc04_services/bcm2835-camera/controls.c +++ /dev/null @@ -1,1399 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Broadcom BCM2835 V4L2 driver - * - * Copyright © 2013 Raspberry Pi (Trading) Ltd. - * - * Authors: Vincent Sanders @ Collabora - * Dave Stevenson @ Broadcom - * (now dave.stevenson@raspberrypi.org) - * Simon Mellor @ Broadcom - * Luke Diamand @ Broadcom - */ - -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <media/videobuf2-vmalloc.h> -#include <media/v4l2-device.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-ctrls.h> -#include <media/v4l2-fh.h> -#include <media/v4l2-event.h> -#include <media/v4l2-common.h> - -#include "../vchiq-mmal/mmal-common.h" -#include "../vchiq-mmal/mmal-vchiq.h" -#include "../vchiq-mmal/mmal-parameters.h" -#include "bcm2835-camera.h" - -/* The supported V4L2_CID_AUTO_EXPOSURE_BIAS values are from -4.0 to +4.0. - * MMAL values are in 1/6th increments so the MMAL range is -24 to +24. - * V4L2 docs say value "is expressed in terms of EV, drivers should interpret - * the values as 0.001 EV units, where the value 1000 stands for +1 EV." - * V4L2 is limited to a max of 32 values in a menu, so count in 1/3rds from - * -4 to +4 - */ -static const s64 ev_bias_qmenu[] = { - -4000, -3667, -3333, - -3000, -2667, -2333, - -2000, -1667, -1333, - -1000, -667, -333, - 0, 333, 667, - 1000, 1333, 1667, - 2000, 2333, 2667, - 3000, 3333, 3667, - 4000 -}; - -/* Supported ISO values (*1000) - * ISOO = auto ISO - */ -static const s64 iso_qmenu[] = { - 0, 100000, 200000, 400000, 800000, -}; - -static const u32 iso_values[] = { - 0, 100, 200, 400, 800, -}; - -enum bcm2835_mmal_ctrl_type { - MMAL_CONTROL_TYPE_STD, - MMAL_CONTROL_TYPE_STD_MENU, - MMAL_CONTROL_TYPE_INT_MENU, - MMAL_CONTROL_TYPE_CLUSTER, /* special cluster entry */ -}; - -struct bcm2835_mmal_v4l2_ctrl { - u32 id; /* v4l2 control identifier */ - enum bcm2835_mmal_ctrl_type type; - /* control minimum value or - * mask for MMAL_CONTROL_TYPE_STD_MENU - */ - s64 min; - s64 max; /* maximum value of control */ - s64 def; /* default value of control */ - u64 step; /* step size of the control */ - const s64 *imenu; /* integer menu array */ - u32 mmal_id; /* mmal parameter id */ - int (*setter)(struct bcm2835_mmal_dev *dev, struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl); -}; - -struct v4l2_to_mmal_effects_setting { - u32 v4l2_effect; - u32 mmal_effect; - s32 col_fx_enable; - s32 col_fx_fixed_cbcr; - u32 u; - u32 v; - u32 num_effect_params; - u32 effect_params[MMAL_MAX_IMAGEFX_PARAMETERS]; -}; - -static const struct v4l2_to_mmal_effects_setting - v4l2_to_mmal_effects_values[] = { - { V4L2_COLORFX_NONE, MMAL_PARAM_IMAGEFX_NONE, - 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_BW, MMAL_PARAM_IMAGEFX_NONE, - 1, 0, 128, 128, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_SEPIA, MMAL_PARAM_IMAGEFX_NONE, - 1, 0, 87, 151, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_NEGATIVE, MMAL_PARAM_IMAGEFX_NEGATIVE, - 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_EMBOSS, MMAL_PARAM_IMAGEFX_EMBOSS, - 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_SKETCH, MMAL_PARAM_IMAGEFX_SKETCH, - 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_SKY_BLUE, MMAL_PARAM_IMAGEFX_PASTEL, - 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_GRASS_GREEN, MMAL_PARAM_IMAGEFX_WATERCOLOUR, - 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_SKIN_WHITEN, MMAL_PARAM_IMAGEFX_WASHEDOUT, - 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_VIVID, MMAL_PARAM_IMAGEFX_SATURATION, - 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_AQUA, MMAL_PARAM_IMAGEFX_NONE, - 1, 0, 171, 121, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_ART_FREEZE, MMAL_PARAM_IMAGEFX_HATCH, - 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_SILHOUETTE, MMAL_PARAM_IMAGEFX_FILM, - 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, - { V4L2_COLORFX_SOLARIZATION, MMAL_PARAM_IMAGEFX_SOLARIZE, - 0, 0, 0, 0, 5, {1, 128, 160, 160, 48} }, - { V4L2_COLORFX_ANTIQUE, MMAL_PARAM_IMAGEFX_COLOURBALANCE, - 0, 0, 0, 0, 3, {108, 274, 238, 0, 0} }, - { V4L2_COLORFX_SET_CBCR, MMAL_PARAM_IMAGEFX_NONE, - 1, 1, 0, 0, 0, {0, 0, 0, 0, 0} } -}; - -struct v4l2_mmal_scene_config { - enum v4l2_scene_mode v4l2_scene; - enum mmal_parameter_exposuremode exposure_mode; - enum mmal_parameter_exposuremeteringmode metering_mode; -}; - -static const struct v4l2_mmal_scene_config scene_configs[] = { - /* V4L2_SCENE_MODE_NONE automatically added */ - { - V4L2_SCENE_MODE_NIGHT, - MMAL_PARAM_EXPOSUREMODE_NIGHT, - MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE - }, - { - V4L2_SCENE_MODE_SPORTS, - MMAL_PARAM_EXPOSUREMODE_SPORTS, - MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE - }, -}; - -/* control handlers*/ - -static int ctrl_set_rational(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - struct s32_fract rational_value; - struct vchiq_mmal_port *control; - - control = &dev->component[COMP_CAMERA]->control; - - rational_value.numerator = ctrl->val; - rational_value.denominator = 100; - - return vchiq_mmal_port_parameter_set(dev->instance, control, - mmal_ctrl->mmal_id, - &rational_value, - sizeof(rational_value)); -} - -static int ctrl_set_value(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - u32 u32_value; - struct vchiq_mmal_port *control; - - control = &dev->component[COMP_CAMERA]->control; - - u32_value = ctrl->val; - - return vchiq_mmal_port_parameter_set(dev->instance, control, - mmal_ctrl->mmal_id, - &u32_value, sizeof(u32_value)); -} - -static int ctrl_set_iso(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - u32 u32_value; - struct vchiq_mmal_port *control; - - if (ctrl->val > mmal_ctrl->max || ctrl->val < mmal_ctrl->min) - return 1; - - if (ctrl->id == V4L2_CID_ISO_SENSITIVITY) - dev->iso = iso_values[ctrl->val]; - else if (ctrl->id == V4L2_CID_ISO_SENSITIVITY_AUTO) - dev->manual_iso_enabled = - (ctrl->val == V4L2_ISO_SENSITIVITY_MANUAL); - - control = &dev->component[COMP_CAMERA]->control; - - if (dev->manual_iso_enabled) - u32_value = dev->iso; - else - u32_value = 0; - - return vchiq_mmal_port_parameter_set(dev->instance, control, - MMAL_PARAMETER_ISO, - &u32_value, sizeof(u32_value)); -} - -static int ctrl_set_value_ev(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - s32 s32_value; - struct vchiq_mmal_port *control; - - control = &dev->component[COMP_CAMERA]->control; - - s32_value = (ctrl->val - 12) * 2; /* Convert from index to 1/6ths */ - - return vchiq_mmal_port_parameter_set(dev->instance, control, - mmal_ctrl->mmal_id, - &s32_value, sizeof(s32_value)); -} - -static int ctrl_set_rotate(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - int ret; - u32 u32_value; - struct vchiq_mmal_component *camera; - - camera = dev->component[COMP_CAMERA]; - - u32_value = ((ctrl->val % 360) / 90) * 90; - - ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0], - mmal_ctrl->mmal_id, - &u32_value, sizeof(u32_value)); - if (ret < 0) - return ret; - - ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1], - mmal_ctrl->mmal_id, - &u32_value, sizeof(u32_value)); - if (ret < 0) - return ret; - - return vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2], - mmal_ctrl->mmal_id, - &u32_value, sizeof(u32_value)); -} - -static int ctrl_set_flip(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - int ret; - u32 u32_value; - struct vchiq_mmal_component *camera; - - if (ctrl->id == V4L2_CID_HFLIP) - dev->hflip = ctrl->val; - else - dev->vflip = ctrl->val; - - camera = dev->component[COMP_CAMERA]; - - if (dev->hflip && dev->vflip) - u32_value = MMAL_PARAM_MIRROR_BOTH; - else if (dev->hflip) - u32_value = MMAL_PARAM_MIRROR_HORIZONTAL; - else if (dev->vflip) - u32_value = MMAL_PARAM_MIRROR_VERTICAL; - else - u32_value = MMAL_PARAM_MIRROR_NONE; - - ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[0], - mmal_ctrl->mmal_id, - &u32_value, sizeof(u32_value)); - if (ret < 0) - return ret; - - ret = vchiq_mmal_port_parameter_set(dev->instance, &camera->output[1], - mmal_ctrl->mmal_id, - &u32_value, sizeof(u32_value)); - if (ret < 0) - return ret; - - return vchiq_mmal_port_parameter_set(dev->instance, &camera->output[2], - mmal_ctrl->mmal_id, - &u32_value, sizeof(u32_value)); -} - -static int ctrl_set_exposure(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode_user; - u32 shutter_speed = 0; - struct vchiq_mmal_port *control; - int ret = 0; - - control = &dev->component[COMP_CAMERA]->control; - - if (mmal_ctrl->mmal_id == MMAL_PARAMETER_SHUTTER_SPEED) { - /* V4L2 is in 100usec increments. - * MMAL is 1usec. - */ - dev->manual_shutter_speed = ctrl->val * 100; - } else if (mmal_ctrl->mmal_id == MMAL_PARAMETER_EXPOSURE_MODE) { - switch (ctrl->val) { - case V4L2_EXPOSURE_AUTO: - exp_mode = MMAL_PARAM_EXPOSUREMODE_AUTO; - break; - - case V4L2_EXPOSURE_MANUAL: - exp_mode = MMAL_PARAM_EXPOSUREMODE_OFF; - break; - } - dev->exposure_mode_user = exp_mode; - dev->exposure_mode_v4l2_user = ctrl->val; - } else if (mmal_ctrl->id == V4L2_CID_EXPOSURE_AUTO_PRIORITY) { - dev->exp_auto_priority = ctrl->val; - } - - if (dev->scene_mode == V4L2_SCENE_MODE_NONE) { - if (exp_mode == MMAL_PARAM_EXPOSUREMODE_OFF) - shutter_speed = dev->manual_shutter_speed; - - ret = vchiq_mmal_port_parameter_set(dev->instance, - control, - MMAL_PARAMETER_SHUTTER_SPEED, - &shutter_speed, - sizeof(shutter_speed)); - ret += vchiq_mmal_port_parameter_set(dev->instance, - control, - MMAL_PARAMETER_EXPOSURE_MODE, - &exp_mode, - sizeof(u32)); - dev->exposure_mode_active = exp_mode; - } - /* exposure_dynamic_framerate (V4L2_CID_EXPOSURE_AUTO_PRIORITY) should - * always apply irrespective of scene mode. - */ - ret += set_framerate_params(dev); - - return ret; -} - -static int ctrl_set_metering_mode(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - switch (ctrl->val) { - case V4L2_EXPOSURE_METERING_AVERAGE: - dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE; - break; - - case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED: - dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT; - break; - - case V4L2_EXPOSURE_METERING_SPOT: - dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT; - break; - - case V4L2_EXPOSURE_METERING_MATRIX: - dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX; - break; - } - - if (dev->scene_mode == V4L2_SCENE_MODE_NONE) { - struct vchiq_mmal_port *control; - u32 u32_value = dev->metering_mode; - - control = &dev->component[COMP_CAMERA]->control; - - return vchiq_mmal_port_parameter_set(dev->instance, control, - mmal_ctrl->mmal_id, - &u32_value, sizeof(u32_value)); - } else { - return 0; - } -} - -static int ctrl_set_flicker_avoidance(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - u32 u32_value; - struct vchiq_mmal_port *control; - - control = &dev->component[COMP_CAMERA]->control; - - switch (ctrl->val) { - case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED: - u32_value = MMAL_PARAM_FLICKERAVOID_OFF; - break; - case V4L2_CID_POWER_LINE_FREQUENCY_50HZ: - u32_value = MMAL_PARAM_FLICKERAVOID_50HZ; - break; - case V4L2_CID_POWER_LINE_FREQUENCY_60HZ: - u32_value = MMAL_PARAM_FLICKERAVOID_60HZ; - break; - case V4L2_CID_POWER_LINE_FREQUENCY_AUTO: - u32_value = MMAL_PARAM_FLICKERAVOID_AUTO; - break; - } - - return vchiq_mmal_port_parameter_set(dev->instance, control, - mmal_ctrl->mmal_id, - &u32_value, sizeof(u32_value)); -} - -static int ctrl_set_awb_mode(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - u32 u32_value; - struct vchiq_mmal_port *control; - - control = &dev->component[COMP_CAMERA]->control; - - switch (ctrl->val) { - case V4L2_WHITE_BALANCE_MANUAL: - u32_value = MMAL_PARAM_AWBMODE_OFF; - break; - - case V4L2_WHITE_BALANCE_AUTO: - u32_value = MMAL_PARAM_AWBMODE_AUTO; - break; - - case V4L2_WHITE_BALANCE_INCANDESCENT: - u32_value = MMAL_PARAM_AWBMODE_INCANDESCENT; - break; - - case V4L2_WHITE_BALANCE_FLUORESCENT: - u32_value = MMAL_PARAM_AWBMODE_FLUORESCENT; - break; - - case V4L2_WHITE_BALANCE_FLUORESCENT_H: - u32_value = MMAL_PARAM_AWBMODE_TUNGSTEN; - break; - - case V4L2_WHITE_BALANCE_HORIZON: - u32_value = MMAL_PARAM_AWBMODE_HORIZON; - break; - - case V4L2_WHITE_BALANCE_DAYLIGHT: - u32_value = MMAL_PARAM_AWBMODE_SUNLIGHT; - break; - - case V4L2_WHITE_BALANCE_FLASH: - u32_value = MMAL_PARAM_AWBMODE_FLASH; - break; - - case V4L2_WHITE_BALANCE_CLOUDY: - u32_value = MMAL_PARAM_AWBMODE_CLOUDY; - break; - - case V4L2_WHITE_BALANCE_SHADE: - u32_value = MMAL_PARAM_AWBMODE_SHADE; - break; - } - - return vchiq_mmal_port_parameter_set(dev->instance, control, - mmal_ctrl->mmal_id, - &u32_value, sizeof(u32_value)); -} - -static int ctrl_set_awb_gains(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - struct vchiq_mmal_port *control; - struct mmal_parameter_awbgains gains; - - control = &dev->component[COMP_CAMERA]->control; - - if (ctrl->id == V4L2_CID_RED_BALANCE) - dev->red_gain = ctrl->val; - else if (ctrl->id == V4L2_CID_BLUE_BALANCE) - dev->blue_gain = ctrl->val; - - gains.r_gain.numerator = dev->red_gain; - gains.r_gain.denominator = 1000; - gains.b_gain.numerator = dev->blue_gain; - gains.b_gain.denominator = 1000; - - return vchiq_mmal_port_parameter_set(dev->instance, control, - mmal_ctrl->mmal_id, - &gains, sizeof(gains)); -} - -static int ctrl_set_image_effect(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - int ret = -EINVAL; - int i, j; - struct vchiq_mmal_port *control; - struct mmal_parameter_imagefx_parameters imagefx; - - for (i = 0; i < ARRAY_SIZE(v4l2_to_mmal_effects_values); i++) { - if (ctrl->val != v4l2_to_mmal_effects_values[i].v4l2_effect) - continue; - - imagefx.effect = - v4l2_to_mmal_effects_values[i].mmal_effect; - imagefx.num_effect_params = - v4l2_to_mmal_effects_values[i].num_effect_params; - - if (imagefx.num_effect_params > MMAL_MAX_IMAGEFX_PARAMETERS) - imagefx.num_effect_params = MMAL_MAX_IMAGEFX_PARAMETERS; - - for (j = 0; j < imagefx.num_effect_params; j++) - imagefx.effect_parameter[j] = - v4l2_to_mmal_effects_values[i].effect_params[j]; - - dev->colourfx.enable = - v4l2_to_mmal_effects_values[i].col_fx_enable; - if (!v4l2_to_mmal_effects_values[i].col_fx_fixed_cbcr) { - dev->colourfx.u = v4l2_to_mmal_effects_values[i].u; - dev->colourfx.v = v4l2_to_mmal_effects_values[i].v; - } - - control = &dev->component[COMP_CAMERA]->control; - - ret = vchiq_mmal_port_parameter_set(dev->instance, control, - MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, - &imagefx, sizeof(imagefx)); - if (ret) - goto exit; - - ret = vchiq_mmal_port_parameter_set(dev->instance, control, - MMAL_PARAMETER_COLOUR_EFFECT, - &dev->colourfx, sizeof(dev->colourfx)); - } - -exit: - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "mmal_ctrl:%p ctrl id:0x%x ctrl val:%d imagefx:0x%x color_effect:%s u:%d v:%d ret %d(%d)\n", - mmal_ctrl, ctrl->id, ctrl->val, imagefx.effect, - dev->colourfx.enable ? "true" : "false", - dev->colourfx.u, dev->colourfx.v, - ret, (ret == 0 ? 0 : -EINVAL)); - return (ret == 0 ? 0 : -EINVAL); -} - -static int ctrl_set_colfx(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - int ret; - struct vchiq_mmal_port *control; - - control = &dev->component[COMP_CAMERA]->control; - - dev->colourfx.u = (ctrl->val & 0xff00) >> 8; - dev->colourfx.v = ctrl->val & 0xff; - - ret = vchiq_mmal_port_parameter_set(dev->instance, control, - MMAL_PARAMETER_COLOUR_EFFECT, - &dev->colourfx, - sizeof(dev->colourfx)); - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s: After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n", - __func__, mmal_ctrl, ctrl->id, ctrl->val, ret, - (ret == 0 ? 0 : -EINVAL)); - return (ret == 0 ? 0 : -EINVAL); -} - -static int ctrl_set_bitrate(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - int ret; - struct vchiq_mmal_port *encoder_out; - - dev->capture.encode_bitrate = ctrl->val; - - encoder_out = &dev->component[COMP_VIDEO_ENCODE]->output[0]; - - ret = vchiq_mmal_port_parameter_set(dev->instance, encoder_out, - mmal_ctrl->mmal_id, &ctrl->val, - sizeof(ctrl->val)); - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s: After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n", - __func__, mmal_ctrl, ctrl->id, ctrl->val, ret, - (ret == 0 ? 0 : -EINVAL)); - - /* - * Older firmware versions (pre July 2019) have a bug in handling - * MMAL_PARAMETER_VIDEO_BIT_RATE that result in the call - * returning -MMAL_MSG_STATUS_EINVAL. So ignore errors from this call. - */ - return 0; -} - -static int ctrl_set_bitrate_mode(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - u32 bitrate_mode; - struct vchiq_mmal_port *encoder_out; - - encoder_out = &dev->component[COMP_VIDEO_ENCODE]->output[0]; - - dev->capture.encode_bitrate_mode = ctrl->val; - switch (ctrl->val) { - default: - case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR: - bitrate_mode = MMAL_VIDEO_RATECONTROL_VARIABLE; - break; - case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR: - bitrate_mode = MMAL_VIDEO_RATECONTROL_CONSTANT; - break; - } - - vchiq_mmal_port_parameter_set(dev->instance, encoder_out, - mmal_ctrl->mmal_id, - &bitrate_mode, - sizeof(bitrate_mode)); - return 0; -} - -static int ctrl_set_image_encode_output(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - u32 u32_value; - struct vchiq_mmal_port *jpeg_out; - - jpeg_out = &dev->component[COMP_IMAGE_ENCODE]->output[0]; - - u32_value = ctrl->val; - - return vchiq_mmal_port_parameter_set(dev->instance, jpeg_out, - mmal_ctrl->mmal_id, - &u32_value, sizeof(u32_value)); -} - -static int ctrl_set_video_encode_param_output(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - u32 u32_value; - struct vchiq_mmal_port *vid_enc_ctl; - - vid_enc_ctl = &dev->component[COMP_VIDEO_ENCODE]->output[0]; - - u32_value = ctrl->val; - - return vchiq_mmal_port_parameter_set(dev->instance, vid_enc_ctl, - mmal_ctrl->mmal_id, - &u32_value, sizeof(u32_value)); -} - -static int ctrl_set_video_encode_profile_level(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - struct mmal_parameter_video_profile param; - int ret = 0; - - if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) { - switch (ctrl->val) { - case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: - case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: - case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: - case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: - dev->capture.enc_profile = ctrl->val; - break; - default: - ret = -EINVAL; - break; - } - } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) { - switch (ctrl->val) { - case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: - case V4L2_MPEG_VIDEO_H264_LEVEL_1B: - case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: - case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: - case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: - case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: - case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: - case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: - case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: - case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: - case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: - case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: - dev->capture.enc_level = ctrl->val; - break; - default: - ret = -EINVAL; - break; - } - } - - if (!ret) { - switch (dev->capture.enc_profile) { - case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: - param.profile = MMAL_VIDEO_PROFILE_H264_BASELINE; - break; - case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: - param.profile = - MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE; - break; - case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: - param.profile = MMAL_VIDEO_PROFILE_H264_MAIN; - break; - case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: - param.profile = MMAL_VIDEO_PROFILE_H264_HIGH; - break; - default: - /* Should never get here */ - break; - } - - switch (dev->capture.enc_level) { - case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: - param.level = MMAL_VIDEO_LEVEL_H264_1; - break; - case V4L2_MPEG_VIDEO_H264_LEVEL_1B: - param.level = MMAL_VIDEO_LEVEL_H264_1b; - break; - case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: - param.level = MMAL_VIDEO_LEVEL_H264_11; - break; - case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: - param.level = MMAL_VIDEO_LEVEL_H264_12; - break; - case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: - param.level = MMAL_VIDEO_LEVEL_H264_13; - break; - case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: - param.level = MMAL_VIDEO_LEVEL_H264_2; - break; - case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: - param.level = MMAL_VIDEO_LEVEL_H264_21; - break; - case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: - param.level = MMAL_VIDEO_LEVEL_H264_22; - break; - case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: - param.level = MMAL_VIDEO_LEVEL_H264_3; - break; - case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: - param.level = MMAL_VIDEO_LEVEL_H264_31; - break; - case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: - param.level = MMAL_VIDEO_LEVEL_H264_32; - break; - case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: - param.level = MMAL_VIDEO_LEVEL_H264_4; - break; - default: - /* Should never get here */ - break; - } - - ret = vchiq_mmal_port_parameter_set(dev->instance, - &dev->component[COMP_VIDEO_ENCODE]->output[0], - mmal_ctrl->mmal_id, - ¶m, sizeof(param)); - } - return ret; -} - -static int ctrl_set_scene_mode(struct bcm2835_mmal_dev *dev, - struct v4l2_ctrl *ctrl, - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) -{ - int ret = 0; - int shutter_speed; - struct vchiq_mmal_port *control; - - v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, - "scene mode selected %d, was %d\n", ctrl->val, - dev->scene_mode); - control = &dev->component[COMP_CAMERA]->control; - - if (ctrl->val == dev->scene_mode) - return 0; - - if (ctrl->val == V4L2_SCENE_MODE_NONE) { - /* Restore all user selections */ - dev->scene_mode = V4L2_SCENE_MODE_NONE; - - if (dev->exposure_mode_user == MMAL_PARAM_EXPOSUREMODE_OFF) - shutter_speed = dev->manual_shutter_speed; - else - shutter_speed = 0; - - v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n", - __func__, shutter_speed, dev->exposure_mode_user, - dev->metering_mode); - ret = vchiq_mmal_port_parameter_set(dev->instance, - control, - MMAL_PARAMETER_SHUTTER_SPEED, - &shutter_speed, - sizeof(shutter_speed)); - ret += vchiq_mmal_port_parameter_set(dev->instance, - control, - MMAL_PARAMETER_EXPOSURE_MODE, - &dev->exposure_mode_user, - sizeof(u32)); - dev->exposure_mode_active = dev->exposure_mode_user; - ret += vchiq_mmal_port_parameter_set(dev->instance, - control, - MMAL_PARAMETER_EXP_METERING_MODE, - &dev->metering_mode, - sizeof(u32)); - ret += set_framerate_params(dev); - } else { - /* Set up scene mode */ - int i; - const struct v4l2_mmal_scene_config *scene = NULL; - int shutter_speed; - enum mmal_parameter_exposuremode exposure_mode; - enum mmal_parameter_exposuremeteringmode metering_mode; - - for (i = 0; i < ARRAY_SIZE(scene_configs); i++) { - if (scene_configs[i].v4l2_scene == ctrl->val) { - scene = &scene_configs[i]; - break; - } - } - if (!scene) - return -EINVAL; - if (i >= ARRAY_SIZE(scene_configs)) - return -EINVAL; - - /* Set all the values */ - dev->scene_mode = ctrl->val; - - if (scene->exposure_mode == MMAL_PARAM_EXPOSUREMODE_OFF) - shutter_speed = dev->manual_shutter_speed; - else - shutter_speed = 0; - exposure_mode = scene->exposure_mode; - metering_mode = scene->metering_mode; - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n", - __func__, shutter_speed, exposure_mode, metering_mode); - - ret = vchiq_mmal_port_parameter_set(dev->instance, control, - MMAL_PARAMETER_SHUTTER_SPEED, - &shutter_speed, - sizeof(shutter_speed)); - ret += vchiq_mmal_port_parameter_set(dev->instance, control, - MMAL_PARAMETER_EXPOSURE_MODE, - &exposure_mode, - sizeof(u32)); - dev->exposure_mode_active = exposure_mode; - ret += vchiq_mmal_port_parameter_set(dev->instance, control, - MMAL_PARAMETER_EXPOSURE_MODE, - &exposure_mode, - sizeof(u32)); - ret += vchiq_mmal_port_parameter_set(dev->instance, control, - MMAL_PARAMETER_EXP_METERING_MODE, - &metering_mode, - sizeof(u32)); - ret += set_framerate_params(dev); - } - if (ret) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "%s: Setting scene to %d, ret=%d\n", - __func__, ctrl->val, ret); - ret = -EINVAL; - } - return 0; -} - -static int bcm2835_mmal_s_ctrl(struct v4l2_ctrl *ctrl) -{ - struct bcm2835_mmal_dev *dev = container_of(ctrl->handler, struct bcm2835_mmal_dev, - ctrl_handler); - const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl = ctrl->priv; - int ret; - - if (!mmal_ctrl || mmal_ctrl->id != ctrl->id || !mmal_ctrl->setter) { - pr_warn("mmal_ctrl:%p ctrl id:%d\n", mmal_ctrl, ctrl->id); - return -EINVAL; - } - - ret = mmal_ctrl->setter(dev, ctrl, mmal_ctrl); - if (ret) - pr_warn("ctrl id:%d/MMAL param %08X- returned ret %d\n", - ctrl->id, mmal_ctrl->mmal_id, ret); - return ret; -} - -static const struct v4l2_ctrl_ops bcm2835_mmal_ctrl_ops = { - .s_ctrl = bcm2835_mmal_s_ctrl, -}; - -static const struct bcm2835_mmal_v4l2_ctrl v4l2_ctrls[V4L2_CTRL_COUNT] = { - { - .id = V4L2_CID_SATURATION, - .type = MMAL_CONTROL_TYPE_STD, - .min = -100, - .max = 100, - .def = 0, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_SATURATION, - .setter = ctrl_set_rational, - }, - { - .id = V4L2_CID_SHARPNESS, - .type = MMAL_CONTROL_TYPE_STD, - .min = -100, - .max = 100, - .def = 0, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_SHARPNESS, - .setter = ctrl_set_rational, - }, - { - .id = V4L2_CID_CONTRAST, - .type = MMAL_CONTROL_TYPE_STD, - .min = -100, - .max = 100, - .def = 0, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_CONTRAST, - .setter = ctrl_set_rational, - }, - { - .id = V4L2_CID_BRIGHTNESS, - .type = MMAL_CONTROL_TYPE_STD, - .min = 0, - .max = 100, - .def = 50, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_BRIGHTNESS, - .setter = ctrl_set_rational, - }, - { - .id = V4L2_CID_ISO_SENSITIVITY, - .type = MMAL_CONTROL_TYPE_INT_MENU, - .min = 0, - .max = ARRAY_SIZE(iso_qmenu) - 1, - .def = 0, - .step = 1, - .imenu = iso_qmenu, - .mmal_id = MMAL_PARAMETER_ISO, - .setter = ctrl_set_iso, - }, - { - .id = V4L2_CID_ISO_SENSITIVITY_AUTO, - .type = MMAL_CONTROL_TYPE_STD_MENU, - .min = 0, - .max = V4L2_ISO_SENSITIVITY_AUTO, - .def = V4L2_ISO_SENSITIVITY_AUTO, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_ISO, - .setter = ctrl_set_iso, - }, - { - .id = V4L2_CID_IMAGE_STABILIZATION, - .type = MMAL_CONTROL_TYPE_STD, - .min = 0, - .max = 1, - .def = 0, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_VIDEO_STABILISATION, - .setter = ctrl_set_value, - }, - { - .id = V4L2_CID_EXPOSURE_AUTO, - .type = MMAL_CONTROL_TYPE_STD_MENU, - .min = ~0x03, - .max = V4L2_EXPOSURE_APERTURE_PRIORITY, - .def = V4L2_EXPOSURE_AUTO, - .step = 0, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_EXPOSURE_MODE, - .setter = ctrl_set_exposure, - }, - { - .id = V4L2_CID_EXPOSURE_ABSOLUTE, - .type = MMAL_CONTROL_TYPE_STD, - /* Units of 100usecs */ - .min = 1, - .max = 1 * 1000 * 10, - .def = 100 * 10, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_SHUTTER_SPEED, - .setter = ctrl_set_exposure, - }, - { - .id = V4L2_CID_AUTO_EXPOSURE_BIAS, - .type = MMAL_CONTROL_TYPE_INT_MENU, - .min = 0, - .max = ARRAY_SIZE(ev_bias_qmenu) - 1, - .def = (ARRAY_SIZE(ev_bias_qmenu) + 1) / 2 - 1, - .step = 0, - .imenu = ev_bias_qmenu, - .mmal_id = MMAL_PARAMETER_EXPOSURE_COMP, - .setter = ctrl_set_value_ev, - }, - { - .id = V4L2_CID_EXPOSURE_AUTO_PRIORITY, - .type = MMAL_CONTROL_TYPE_STD, - .min = 0, - .max = 1, - .def = 0, - .step = 1, - .imenu = NULL, - /* Dummy MMAL ID as it gets mapped into FPS range */ - .mmal_id = 0, - .setter = ctrl_set_exposure, - }, - { - .id = V4L2_CID_EXPOSURE_METERING, - .type = MMAL_CONTROL_TYPE_STD_MENU, - .min = ~0xf, - .max = V4L2_EXPOSURE_METERING_MATRIX, - .def = V4L2_EXPOSURE_METERING_AVERAGE, - .step = 0, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_EXP_METERING_MODE, - .setter = ctrl_set_metering_mode, - }, - { - .id = V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, - .type = MMAL_CONTROL_TYPE_STD_MENU, - .min = ~0x3ff, - .max = V4L2_WHITE_BALANCE_SHADE, - .def = V4L2_WHITE_BALANCE_AUTO, - .step = 0, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_AWB_MODE, - .setter = ctrl_set_awb_mode, - }, - { - .id = V4L2_CID_RED_BALANCE, - .type = MMAL_CONTROL_TYPE_STD, - .min = 1, - .max = 7999, - .def = 1000, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_CUSTOM_AWB_GAINS, - .setter = ctrl_set_awb_gains, - }, - { - .id = V4L2_CID_BLUE_BALANCE, - .type = MMAL_CONTROL_TYPE_STD, - .min = 1, - .max = 7999, - .def = 1000, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_CUSTOM_AWB_GAINS, - .setter = ctrl_set_awb_gains, - }, - { - .id = V4L2_CID_COLORFX, - .type = MMAL_CONTROL_TYPE_STD_MENU, - .min = 0, - .max = V4L2_COLORFX_SET_CBCR, - .def = V4L2_COLORFX_NONE, - .step = 0, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_IMAGE_EFFECT, - .setter = ctrl_set_image_effect, - }, - { - .id = V4L2_CID_COLORFX_CBCR, - .type = MMAL_CONTROL_TYPE_STD, - .min = 0, - .max = 0xffff, - .def = 0x8080, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_COLOUR_EFFECT, - .setter = ctrl_set_colfx, - }, - { - .id = V4L2_CID_ROTATE, - .type = MMAL_CONTROL_TYPE_STD, - .min = 0, - .max = 360, - .def = 0, - .step = 90, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_ROTATION, - .setter = ctrl_set_rotate, - }, - { - .id = V4L2_CID_HFLIP, - .type = MMAL_CONTROL_TYPE_STD, - .min = 0, - .max = 1, - .def = 0, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_MIRROR, - .setter = ctrl_set_flip, - }, - { - .id = V4L2_CID_VFLIP, - .type = MMAL_CONTROL_TYPE_STD, - .min = 0, - .max = 1, - .def = 0, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_MIRROR, - .setter = ctrl_set_flip, - }, - { - .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE, - .type = MMAL_CONTROL_TYPE_STD_MENU, - .min = 0, - .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, - .def = 0, - .step = 0, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_RATECONTROL, - .setter = ctrl_set_bitrate_mode, - }, - { - .id = V4L2_CID_MPEG_VIDEO_BITRATE, - .type = MMAL_CONTROL_TYPE_STD, - .min = 25 * 1000, - .max = 25 * 1000 * 1000, - .def = 10 * 1000 * 1000, - .step = 25 * 1000, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_VIDEO_BIT_RATE, - .setter = ctrl_set_bitrate, - }, - { - .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, - .type = MMAL_CONTROL_TYPE_STD, - .min = 1, - .max = 100, - .def = 30, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_JPEG_Q_FACTOR, - .setter = ctrl_set_image_encode_output, - }, - { - .id = V4L2_CID_POWER_LINE_FREQUENCY, - .type = MMAL_CONTROL_TYPE_STD_MENU, - .min = 0, - .max = V4L2_CID_POWER_LINE_FREQUENCY_AUTO, - .def = 1, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_FLICKER_AVOID, - .setter = ctrl_set_flicker_avoidance, - }, - { - .id = V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, - .type = MMAL_CONTROL_TYPE_STD, - .min = 0, - .max = 1, - .def = 0, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, - .setter = ctrl_set_video_encode_param_output, - }, - { - .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE, - .type = MMAL_CONTROL_TYPE_STD_MENU, - .min = ~(BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | - BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | - BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | - BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)), - .max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, - .def = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_PROFILE, - .setter = ctrl_set_video_encode_profile_level, - }, - { - .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL, - .type = MMAL_CONTROL_TYPE_STD_MENU, - .min = ~(BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | - BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0)), - .max = V4L2_MPEG_VIDEO_H264_LEVEL_4_0, - .def = V4L2_MPEG_VIDEO_H264_LEVEL_4_0, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_PROFILE, - .setter = ctrl_set_video_encode_profile_level, - }, - { - .id = V4L2_CID_SCENE_MODE, - .type = MMAL_CONTROL_TYPE_STD_MENU, - /* mask is computed at runtime */ - .min = -1, - .max = V4L2_SCENE_MODE_TEXT, - .def = V4L2_SCENE_MODE_NONE, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_PROFILE, - .setter = ctrl_set_scene_mode, - }, - { - .id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, - .type = MMAL_CONTROL_TYPE_STD, - .min = 0, - .max = 0x7FFFFFFF, - .def = 60, - .step = 1, - .imenu = NULL, - .mmal_id = MMAL_PARAMETER_INTRAPERIOD, - .setter = ctrl_set_video_encode_param_output, - }, -}; - -int bcm2835_mmal_set_all_camera_controls(struct bcm2835_mmal_dev *dev) -{ - int c; - int ret = 0; - - for (c = 0; c < V4L2_CTRL_COUNT; c++) { - if ((dev->ctrls[c]) && (v4l2_ctrls[c].setter)) { - ret = v4l2_ctrls[c].setter(dev, dev->ctrls[c], - &v4l2_ctrls[c]); - if (ret) { - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Failed when setting default values for ctrl %d\n", - c); - break; - } - } - } - return ret; -} - -int set_framerate_params(struct bcm2835_mmal_dev *dev) -{ - struct mmal_parameter_fps_range fps_range; - int ret; - - fps_range.fps_high.numerator = dev->capture.timeperframe.denominator; - fps_range.fps_high.denominator = dev->capture.timeperframe.numerator; - - if ((dev->exposure_mode_active != MMAL_PARAM_EXPOSUREMODE_OFF) && - (dev->exp_auto_priority)) { - /* Variable FPS. Define min FPS as 1fps. */ - fps_range.fps_low.numerator = 1; - fps_range.fps_low.denominator = 1; - } else { - /* Fixed FPS - set min and max to be the same */ - fps_range.fps_low.numerator = fps_range.fps_high.numerator; - fps_range.fps_low.denominator = fps_range.fps_high.denominator; - } - - v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Set fps range to %d/%d to %d/%d\n", - fps_range.fps_low.numerator, - fps_range.fps_low.denominator, - fps_range.fps_high.numerator, - fps_range.fps_high.denominator); - - ret = vchiq_mmal_port_parameter_set(dev->instance, - &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW], - MMAL_PARAMETER_FPS_RANGE, - &fps_range, sizeof(fps_range)); - ret += vchiq_mmal_port_parameter_set(dev->instance, - &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO], - MMAL_PARAMETER_FPS_RANGE, - &fps_range, sizeof(fps_range)); - ret += vchiq_mmal_port_parameter_set(dev->instance, - &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE], - MMAL_PARAMETER_FPS_RANGE, - &fps_range, sizeof(fps_range)); - if (ret) - v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, - "Failed to set fps ret %d\n", ret); - - return ret; -} - -int bcm2835_mmal_init_controls(struct bcm2835_mmal_dev *dev, struct v4l2_ctrl_handler *hdl) -{ - int c; - const struct bcm2835_mmal_v4l2_ctrl *ctrl; - - v4l2_ctrl_handler_init(hdl, V4L2_CTRL_COUNT); - - for (c = 0; c < V4L2_CTRL_COUNT; c++) { - ctrl = &v4l2_ctrls[c]; - - switch (ctrl->type) { - case MMAL_CONTROL_TYPE_STD: - dev->ctrls[c] = v4l2_ctrl_new_std(hdl, &bcm2835_mmal_ctrl_ops, - ctrl->id, ctrl->min, ctrl->max, - ctrl->step, ctrl->def); - break; - - case MMAL_CONTROL_TYPE_STD_MENU: - { - u64 mask = ctrl->min; - - if (ctrl->id == V4L2_CID_SCENE_MODE) { - /* Special handling to work out the mask - * value based on the scene_configs array - * at runtime. Reduces the chance of - * mismatches. - */ - int i; - - mask = BIT(V4L2_SCENE_MODE_NONE); - for (i = 0; - i < ARRAY_SIZE(scene_configs); - i++) { - mask |= BIT(scene_configs[i].v4l2_scene); - } - mask = ~mask; - } - - dev->ctrls[c] = v4l2_ctrl_new_std_menu(hdl, &bcm2835_mmal_ctrl_ops, - ctrl->id, ctrl->max, mask, - ctrl->def); - break; - } - - case MMAL_CONTROL_TYPE_INT_MENU: - dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl, &bcm2835_mmal_ctrl_ops, - ctrl->id, ctrl->max, - ctrl->def, ctrl->imenu); - break; - - case MMAL_CONTROL_TYPE_CLUSTER: - /* skip this entry when constructing controls */ - continue; - } - - if (hdl->error) - break; - - dev->ctrls[c]->priv = (void *)ctrl; - } - - if (hdl->error) { - pr_err("error adding control %d/%d id 0x%x\n", c, - V4L2_CTRL_COUNT, ctrl->id); - return hdl->error; - } - - for (c = 0; c < V4L2_CTRL_COUNT; c++) { - ctrl = &v4l2_ctrls[c]; - - switch (ctrl->type) { - case MMAL_CONTROL_TYPE_CLUSTER: - v4l2_ctrl_auto_cluster(ctrl->min, - &dev->ctrls[c + 1], - ctrl->max, - ctrl->def); - break; - - case MMAL_CONTROL_TYPE_STD: - case MMAL_CONTROL_TYPE_STD_MENU: - case MMAL_CONTROL_TYPE_INT_MENU: - break; - } - } - - return 0; -} diff --git a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h deleted file mode 100644 index ee4469f4fc51..000000000000 --- a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h +++ /dev/null @@ -1,112 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#ifndef VCHIQ_H -#define VCHIQ_H - -#define VCHIQ_MAKE_FOURCC(x0, x1, x2, x3) \ - (((x0) << 24) | ((x1) << 16) | ((x2) << 8) | (x3)) - -enum vchiq_reason { - VCHIQ_SERVICE_OPENED, /* service, -, - */ - VCHIQ_SERVICE_CLOSED, /* service, -, - */ - VCHIQ_MESSAGE_AVAILABLE, /* service, header, - */ - VCHIQ_BULK_TRANSMIT_DONE, /* service, -, bulk_userdata */ - VCHIQ_BULK_RECEIVE_DONE, /* service, -, bulk_userdata */ - VCHIQ_BULK_TRANSMIT_ABORTED, /* service, -, bulk_userdata */ - VCHIQ_BULK_RECEIVE_ABORTED /* service, -, bulk_userdata */ -}; - -enum vchiq_bulk_mode { - VCHIQ_BULK_MODE_CALLBACK, - VCHIQ_BULK_MODE_BLOCKING, - VCHIQ_BULK_MODE_NOCALLBACK, - VCHIQ_BULK_MODE_WAITING /* Reserved for internal use */ -}; - -enum vchiq_service_option { - VCHIQ_SERVICE_OPTION_AUTOCLOSE, - VCHIQ_SERVICE_OPTION_SLOT_QUOTA, - VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA, - VCHIQ_SERVICE_OPTION_SYNCHRONOUS, - VCHIQ_SERVICE_OPTION_TRACE -}; - -struct vchiq_header { - /* The message identifier - opaque to applications. */ - int msgid; - - /* Size of message data. */ - unsigned int size; - - char data[]; /* message */ -}; - -struct vchiq_element { - const void __user *data; - unsigned int size; -}; - -struct vchiq_instance; -struct vchiq_state; - -struct vchiq_service_base { - int fourcc; - int (*callback)(struct vchiq_instance *instance, - enum vchiq_reason reason, - struct vchiq_header *header, - unsigned int handle, - void *cb_data, void __user *cb_userdata); - void *userdata; -}; - -struct vchiq_completion_data_kernel { - enum vchiq_reason reason; - struct vchiq_header *header; - void *service_userdata; - void *cb_data; - void __user *cb_userdata; -}; - -struct vchiq_service_params_kernel { - int fourcc; - int (*callback)(struct vchiq_instance *instance, - enum vchiq_reason reason, - struct vchiq_header *header, - unsigned int handle, - void *cb_data, void __user *cb_userdata); - void *userdata; - short version; /* Increment for non-trivial changes */ - short version_min; /* Update for incompatible changes */ -}; - -extern int vchiq_initialise(struct vchiq_state *state, - struct vchiq_instance **pinstance); -extern int vchiq_shutdown(struct vchiq_instance *instance); -extern int vchiq_connect(struct vchiq_instance *instance); -extern int vchiq_open_service(struct vchiq_instance *instance, - const struct vchiq_service_params_kernel *params, - unsigned int *pservice); -extern int vchiq_close_service(struct vchiq_instance *instance, - unsigned int service); -extern int vchiq_use_service(struct vchiq_instance *instance, unsigned int service); -extern int vchiq_release_service(struct vchiq_instance *instance, - unsigned int service); -extern void vchiq_msg_queue_push(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_header *header); -extern void vchiq_release_message(struct vchiq_instance *instance, unsigned int service, - struct vchiq_header *header); -extern int vchiq_queue_kernel_message(struct vchiq_instance *instance, unsigned int handle, - void *data, unsigned int size); -extern int vchiq_bulk_transmit(struct vchiq_instance *instance, unsigned int service, - const void *data, unsigned int size, void *userdata, - enum vchiq_bulk_mode mode); -extern int vchiq_bulk_receive(struct vchiq_instance *instance, unsigned int service, - void *data, unsigned int size, void *userdata, - enum vchiq_bulk_mode mode); -extern void *vchiq_get_service_userdata(struct vchiq_instance *instance, unsigned int service); -extern int vchiq_get_peer_version(struct vchiq_instance *instance, unsigned int handle, - short *peer_version); -extern struct vchiq_header *vchiq_msg_hold(struct vchiq_instance *instance, unsigned int handle); - -#endif /* VCHIQ_H */ diff --git a/drivers/staging/vc04_services/interface/TESTING b/drivers/staging/vc04_services/interface/TESTING deleted file mode 100644 index c98f688b07e0..000000000000 --- a/drivers/staging/vc04_services/interface/TESTING +++ /dev/null @@ -1,125 +0,0 @@ -This document contains some hints to test the function of the VCHIQ driver -without having additional hardware to the Raspberry Pi. - -* Requirements & limitations - -Testing the VCHIQ driver requires a Raspberry Pi with one of the following SoC: - - BCM2835 ( e.g. Raspberry Pi Zero W ) - - BCM2836 ( e.g. Raspberry Pi 2 ) - - BCM2837 ( e.g. Raspberry Pi 3 B+ ) - -The BCM2711 used in the Raspberry Pi 4 is currently not supported in the -mainline kernel. - -There are no specific requirements to the VideoCore firmware to get VCHIQ -working. - -The test scenarios described in this document based on the tool vchiq_test. -Its source code is available here: https://github.com/raspberrypi/userland - -* Configuration - -Here are the most common kernel configurations: - - 1. BCM2835 target SoC (ARM 32 bit) - - Just use bcm2835_defconfig which already has VCHIQ enabled. - - 2. BCM2836/7 target SoC (ARM 32 bit) - - Use the multi_v7_defconfig as a base and then enable all VCHIQ options. - - 3. BCM2837 target SoC (ARM 64 bit) - - Use the defconfig which has most of the VCHIQ options enabled. - -* Scenarios - - * Initial test - - Check the driver is probed and /dev/vchiq is created - - * Functional test - - Command: vchiq_test -f 10 - - Expected output: - Functional test - iters:10 - ======== iteration 1 ======== - Testing bulk transfer for alignment. - Testing bulk transfer at PAGE_SIZE. - ... - - * Ping test - - Command: vchiq_test -p - - Expected output: - Ping test - service:echo, iters:1000, version 3 - vchi ping (size 0) -> 57.000000us - vchi ping (size 0, 0 async, 0 oneway) -> 122.000000us - vchi bulk (size 0, 0 async, 0 oneway) -> 546.000000us - vchi bulk (size 0, 0 oneway) -> 230.000000us - vchi ping (size 0) -> 49.000000us - vchi ping (size 0, 0 async, 0 oneway) -> 70.000000us - vchi bulk (size 0, 0 async, 0 oneway) -> 296.000000us - vchi bulk (size 0, 0 oneway) -> 266.000000us - vchi ping (size 0, 1 async, 0 oneway) -> 65.000000us - vchi bulk (size 0, 0 oneway) -> 456.000000us - vchi ping (size 0, 2 async, 0 oneway) -> 74.000000us - vchi bulk (size 0, 0 oneway) -> 640.000000us - vchi ping (size 0, 10 async, 0 oneway) -> 125.000000us - vchi bulk (size 0, 0 oneway) -> 2309.000000us - vchi ping (size 0, 0 async, 1 oneway) -> 70.000000us - vchi ping (size 0, 0 async, 2 oneway) -> 76.000000us - vchi ping (size 0, 0 async, 10 oneway) -> 105.000000us - vchi ping (size 0, 10 async, 10 oneway) -> 165.000000us - vchi ping (size 0, 100 async, 0 oneway) -> nanus - vchi bulk (size 0, 0 oneway) -> nanus - vchi ping (size 0, 0 async, 100 oneway) -> nanus - vchi ping (size 0, 100 async, 100 oneway) -> infus - vchi ping (size 0, 200 async, 0 oneway) -> infus - ... - - * Debugfs test - - Command: cat /sys/kernel/debug/vchiq/state - - Example output: - State 0: CONNECTED - tx_pos=0x1e8(@43b0acda), rx_pos=0x170(@05493af8) - Version: 8 (min 3) - Stats: ctrl_tx_count=7, ctrl_rx_count=7, error_count=0 - Slots: 30 available (29 data), 0 recyclable, 0 stalls (0 data) - Platform: 2835 (VC master) - Local: slots 34-64 tx_pos=0x1e8 recycle=0x1f - Slots claimed: - DEBUG: SLOT_HANDLER_COUNT = 20(0x14) - DEBUG: SLOT_HANDLER_LINE = 1937(0x791) - DEBUG: PARSE_LINE = 1864(0x748) - DEBUG: PARSE_HEADER = -249155224(0xf1263168) - DEBUG: PARSE_MSGID = 67362817(0x403e001) - DEBUG: AWAIT_COMPLETION_LINE = 0(0x0) - DEBUG: DEQUEUE_MESSAGE_LINE = 0(0x0) - DEBUG: SERVICE_CALLBACK_LINE = 0(0x0) - DEBUG: MSG_QUEUE_FULL_COUNT = 0(0x0) - DEBUG: COMPLETION_QUEUE_FULL_COUNT = 0(0x0) - Remote: slots 2-32 tx_pos=0x170 recycle=0x1f - Slots claimed: - 2: 10/9 - DEBUG: SLOT_HANDLER_COUNT = 20(0x14) - DEBUG: SLOT_HANDLER_LINE = 1851(0x73b) - DEBUG: PARSE_LINE = 1827(0x723) - DEBUG: PARSE_HEADER = -150330912(0xf70a21e0) - DEBUG: PARSE_MSGID = 67113022(0x400103e) - DEBUG: AWAIT_COMPLETION_LINE = 0(0x0) - DEBUG: DEQUEUE_MESSAGE_LINE = 0(0x0) - DEBUG: SERVICE_CALLBACK_LINE = 0(0x0) - DEBUG: MSG_QUEUE_FULL_COUNT = 0(0x0) - DEBUG: COMPLETION_QUEUE_FULL_COUNT = 0(0x0) - Service 0: LISTENING (ref 1) 'PEEK little-endian (0x4b454550)' remote n/a (msg use 0/3840, slot use 0/15) - Bulk: tx_pending=0 (size 0), rx_pending=0 (size 0) - Ctrl: tx_count=0, tx_bytes=0, rx_count=0, rx_bytes=0 - Bulk: tx_count=0, tx_bytes=0, rx_count=0, rx_bytes=0 - 0 quota stalls, 0 slot stalls, 0 bulk stalls, 0 aborted, 0 errors - instance b511f60b diff --git a/drivers/staging/vc04_services/interface/TODO b/drivers/staging/vc04_services/interface/TODO deleted file mode 100644 index f6f24600aa86..000000000000 --- a/drivers/staging/vc04_services/interface/TODO +++ /dev/null @@ -1,28 +0,0 @@ -* Import drivers using VCHI. - -VCHI is just a tool to let drivers talk to the firmware. Here are -some of the ones we want: - - - vc_mem (https://github.com/raspberrypi/linux/blob/rpi-4.4.y/drivers/char/broadcom/vc_mem.c) - - This driver is what the vcdbg userspace program uses to set up its - requests to the firmware, which are transmitted across VCHIQ. vcdbg - is really useful for debugging firmware interactions. - - - VCSM (https://github.com/raspberrypi/linux/tree/rpi-4.4.y/drivers/char/broadcom/vc_sm) - - This driver is used for talking about regions of VC memory across - firmware protocols including VCHI. We'll want to extend this driver - to manage these buffers as dmabufs so that we can zero-copy import - camera images into vc4 for rendering/display. - -* Documentation - -A short top-down description of this driver's architecture (function of -kthreads, userspace, limitations) could be very helpful for reviewers. - -* Reformat core code with more sane indentations - -The code follows the 80 characters limitation yet tends to go 3 or 4 levels of -indentation deep making it very unpleasant to read. This is specially relevant -in the character driver ioctl code and in the core thread functions. diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c deleted file mode 100644 index 721b15b7e13b..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ /dev/null @@ -1,1473 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* - * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. - * Copyright (c) 2010-2012 Broadcom. All rights reserved. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/sched/signal.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/cdev.h> -#include <linux/fs.h> -#include <linux/device.h> -#include <linux/device/bus.h> -#include <linux/mm.h> -#include <linux/pagemap.h> -#include <linux/bug.h> -#include <linux/completion.h> -#include <linux/list.h> -#include <linux/of.h> -#include <linux/platform_device.h> -#include <linux/compat.h> -#include <linux/dma-mapping.h> -#include <linux/rcupdate.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/uaccess.h> -#include <soc/bcm2835/raspberrypi-firmware.h> - -#include "vchiq_core.h" -#include "vchiq_ioctl.h" -#include "vchiq_arm.h" -#include "vchiq_bus.h" -#include "vchiq_debugfs.h" - -#define DEVICE_NAME "vchiq" - -#define TOTAL_SLOTS (VCHIQ_SLOT_ZERO_SLOTS + 2 * 32) - -#define MAX_FRAGMENTS (VCHIQ_NUM_CURRENT_BULKS * 2) - -#define VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX 0 -#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1 - -#define BELL0 0x00 - -#define ARM_DS_ACTIVE BIT(2) - -/* Override the default prefix, which would be vchiq_arm (from the filename) */ -#undef MODULE_PARAM_PREFIX -#define MODULE_PARAM_PREFIX DEVICE_NAME "." - -#define KEEPALIVE_VER 1 -#define KEEPALIVE_VER_MIN KEEPALIVE_VER - -/* - * The devices implemented in the VCHIQ firmware are not discoverable, - * so we need to maintain a list of them in order to register them with - * the interface. - */ -static struct vchiq_device *bcm2835_audio; -static struct vchiq_device *bcm2835_camera; - -static const struct vchiq_platform_info bcm2835_info = { - .cache_line_size = 32, -}; - -static const struct vchiq_platform_info bcm2836_info = { - .cache_line_size = 64, -}; - -struct vchiq_arm_state { - /* Keepalive-related data */ - struct task_struct *ka_thread; - struct completion ka_evt; - atomic_t ka_use_count; - atomic_t ka_use_ack_count; - atomic_t ka_release_count; - - rwlock_t susp_res_lock; - - struct vchiq_state *state; - - /* - * Global use count for videocore. - * This is equal to the sum of the use counts for all services. When - * this hits zero the videocore suspend procedure will be initiated. - */ - int videocore_use_count; - - /* - * Use count to track requests from videocore peer. - * This use count is not associated with a service, so needs to be - * tracked separately with the state. - */ - int peer_use_count; - - /* - * Flag to indicate that the first vchiq connect has made it through. - * This means that both sides should be fully ready, and we should - * be able to suspend after this point. - */ - int first_connect; -}; - -static int -vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_bulk *bulk_params); - -static irqreturn_t -vchiq_doorbell_irq(int irq, void *dev_id) -{ - struct vchiq_state *state = dev_id; - struct vchiq_drv_mgmt *mgmt; - irqreturn_t ret = IRQ_NONE; - unsigned int status; - - mgmt = dev_get_drvdata(state->dev); - - /* Read (and clear) the doorbell */ - status = readl(mgmt->regs + BELL0); - - if (status & ARM_DS_ACTIVE) { /* Was the doorbell rung? */ - remote_event_pollall(state); - ret = IRQ_HANDLED; - } - - return ret; -} - -/* - * This function is called by the vchiq stack once it has been connected to - * the videocore and clients can start to use the stack. - */ -static void vchiq_call_connected_callbacks(struct vchiq_drv_mgmt *drv_mgmt) -{ - int i; - - if (mutex_lock_killable(&drv_mgmt->connected_mutex)) - return; - - for (i = 0; i < drv_mgmt->num_deferred_callbacks; i++) - drv_mgmt->deferred_callback[i](); - - drv_mgmt->num_deferred_callbacks = 0; - drv_mgmt->connected = true; - mutex_unlock(&drv_mgmt->connected_mutex); -} - -/* - * This function is used to defer initialization until the vchiq stack is - * initialized. If the stack is already initialized, then the callback will - * be made immediately, otherwise it will be deferred until - * vchiq_call_connected_callbacks is called. - */ -void vchiq_add_connected_callback(struct vchiq_device *device, void (*callback)(void)) -{ - struct vchiq_drv_mgmt *drv_mgmt = device->drv_mgmt; - - if (mutex_lock_killable(&drv_mgmt->connected_mutex)) - return; - - if (drv_mgmt->connected) { - /* We're already connected. Call the callback immediately. */ - callback(); - } else { - if (drv_mgmt->num_deferred_callbacks >= VCHIQ_DRV_MAX_CALLBACKS) { - dev_err(&device->dev, - "core: deferred callbacks(%d) exceeded the maximum limit(%d)\n", - drv_mgmt->num_deferred_callbacks, VCHIQ_DRV_MAX_CALLBACKS); - } else { - drv_mgmt->deferred_callback[drv_mgmt->num_deferred_callbacks] = - callback; - drv_mgmt->num_deferred_callbacks++; - } - } - mutex_unlock(&drv_mgmt->connected_mutex); -} -EXPORT_SYMBOL(vchiq_add_connected_callback); - -static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state) -{ - struct device *dev = &pdev->dev; - struct vchiq_drv_mgmt *drv_mgmt = platform_get_drvdata(pdev); - struct rpi_firmware *fw = drv_mgmt->fw; - struct vchiq_slot_zero *vchiq_slot_zero; - void *slot_mem; - dma_addr_t slot_phys; - u32 channelbase; - int slot_mem_size, frag_mem_size; - int err, irq, i; - - /* - * VCHI messages between the CPU and firmware use - * 32-bit bus addresses. - */ - err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); - - if (err < 0) - return err; - - drv_mgmt->fragments_size = 2 * drv_mgmt->info->cache_line_size; - - /* Allocate space for the channels in coherent memory */ - slot_mem_size = PAGE_ALIGN(TOTAL_SLOTS * VCHIQ_SLOT_SIZE); - frag_mem_size = PAGE_ALIGN(drv_mgmt->fragments_size * MAX_FRAGMENTS); - - slot_mem = dmam_alloc_coherent(dev, slot_mem_size + frag_mem_size, - &slot_phys, GFP_KERNEL); - if (!slot_mem) { - dev_err(dev, "could not allocate DMA memory\n"); - return -ENOMEM; - } - - WARN_ON(((unsigned long)slot_mem & (PAGE_SIZE - 1)) != 0); - - vchiq_slot_zero = vchiq_init_slots(dev, slot_mem, slot_mem_size); - if (!vchiq_slot_zero) - return -ENOMEM; - - vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX] = - (int)slot_phys + slot_mem_size; - vchiq_slot_zero->platform_data[VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX] = - MAX_FRAGMENTS; - - drv_mgmt->fragments_base = (char *)slot_mem + slot_mem_size; - - drv_mgmt->free_fragments = drv_mgmt->fragments_base; - for (i = 0; i < (MAX_FRAGMENTS - 1); i++) { - *(char **)&drv_mgmt->fragments_base[i * drv_mgmt->fragments_size] = - &drv_mgmt->fragments_base[(i + 1) * drv_mgmt->fragments_size]; - } - *(char **)&drv_mgmt->fragments_base[i * drv_mgmt->fragments_size] = NULL; - sema_init(&drv_mgmt->free_fragments_sema, MAX_FRAGMENTS); - sema_init(&drv_mgmt->free_fragments_mutex, 1); - - err = vchiq_init_state(state, vchiq_slot_zero, dev); - if (err) - return err; - - drv_mgmt->regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(drv_mgmt->regs)) - return PTR_ERR(drv_mgmt->regs); - - irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return irq; - - err = devm_request_irq(dev, irq, vchiq_doorbell_irq, IRQF_IRQPOLL, - "VCHIQ doorbell", state); - if (err) { - dev_err(dev, "failed to register irq=%d\n", irq); - return err; - } - - /* Send the base address of the slots to VideoCore */ - channelbase = slot_phys; - err = rpi_firmware_property(fw, RPI_FIRMWARE_VCHIQ_INIT, - &channelbase, sizeof(channelbase)); - if (err) { - dev_err(dev, "failed to send firmware property: %d\n", err); - return err; - } - - if (channelbase) { - dev_err(dev, "failed to set channelbase (response: %x)\n", - channelbase); - return -ENXIO; - } - - dev_dbg(&pdev->dev, "arm: vchiq_init - done (slots %p, phys %pad)\n", - vchiq_slot_zero, &slot_phys); - - mutex_init(&drv_mgmt->connected_mutex); - vchiq_call_connected_callbacks(drv_mgmt); - - return 0; -} - -int -vchiq_platform_init_state(struct vchiq_state *state) -{ - struct vchiq_arm_state *platform_state; - - platform_state = devm_kzalloc(state->dev, sizeof(*platform_state), GFP_KERNEL); - if (!platform_state) - return -ENOMEM; - - rwlock_init(&platform_state->susp_res_lock); - - init_completion(&platform_state->ka_evt); - atomic_set(&platform_state->ka_use_count, 0); - atomic_set(&platform_state->ka_use_ack_count, 0); - atomic_set(&platform_state->ka_release_count, 0); - - platform_state->state = state; - - state->platform_state = (struct opaque_platform_state *)platform_state; - - return 0; -} - -static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state *state) -{ - return (struct vchiq_arm_state *)state->platform_state; -} - -static void -vchiq_platform_uninit(struct vchiq_drv_mgmt *mgmt) -{ - struct vchiq_arm_state *arm_state; - - kthread_stop(mgmt->state.sync_thread); - kthread_stop(mgmt->state.recycle_thread); - kthread_stop(mgmt->state.slot_handler_thread); - - arm_state = vchiq_platform_get_arm_state(&mgmt->state); - if (!IS_ERR_OR_NULL(arm_state->ka_thread)) - kthread_stop(arm_state->ka_thread); -} - -void vchiq_dump_platform_state(struct seq_file *f) -{ - seq_puts(f, " Platform: 2835 (VC master)\n"); -} - -#define VCHIQ_INIT_RETRIES 10 -int vchiq_initialise(struct vchiq_state *state, struct vchiq_instance **instance_out) -{ - struct vchiq_instance *instance = NULL; - int i, ret; - - /* - * VideoCore may not be ready due to boot up timing. - * It may never be ready if kernel and firmware are mismatched,so don't - * block forever. - */ - for (i = 0; i < VCHIQ_INIT_RETRIES; i++) { - if (vchiq_remote_initialised(state)) - break; - usleep_range(500, 600); - } - if (i == VCHIQ_INIT_RETRIES) { - dev_err(state->dev, "core: %s: Videocore not initialized\n", __func__); - ret = -ENOTCONN; - goto failed; - } else if (i > 0) { - dev_warn(state->dev, "core: %s: videocore initialized after %d retries\n", - __func__, i); - } - - instance = kzalloc(sizeof(*instance), GFP_KERNEL); - if (!instance) { - ret = -ENOMEM; - goto failed; - } - - instance->connected = 0; - instance->state = state; - mutex_init(&instance->bulk_waiter_list_mutex); - INIT_LIST_HEAD(&instance->bulk_waiter_list); - - *instance_out = instance; - - ret = 0; - -failed: - dev_dbg(state->dev, "core: (%p): returning %d\n", instance, ret); - - return ret; -} -EXPORT_SYMBOL(vchiq_initialise); - -void free_bulk_waiter(struct vchiq_instance *instance) -{ - struct bulk_waiter_node *waiter, *next; - - list_for_each_entry_safe(waiter, next, - &instance->bulk_waiter_list, list) { - list_del(&waiter->list); - dev_dbg(instance->state->dev, - "arm: bulk_waiter - cleaned up %p for pid %d\n", - waiter, waiter->pid); - kfree(waiter); - } -} - -int vchiq_shutdown(struct vchiq_instance *instance) -{ - struct vchiq_state *state = instance->state; - int ret = 0; - - mutex_lock(&state->mutex); - - /* Remove all services */ - vchiq_shutdown_internal(state, instance); - - mutex_unlock(&state->mutex); - - dev_dbg(state->dev, "core: (%p): returning %d\n", instance, ret); - - free_bulk_waiter(instance); - kfree(instance); - - return ret; -} -EXPORT_SYMBOL(vchiq_shutdown); - -static int vchiq_is_connected(struct vchiq_instance *instance) -{ - return instance->connected; -} - -int vchiq_connect(struct vchiq_instance *instance) -{ - struct vchiq_state *state = instance->state; - int ret; - - if (mutex_lock_killable(&state->mutex)) { - dev_dbg(state->dev, - "core: call to mutex_lock failed\n"); - ret = -EAGAIN; - goto failed; - } - ret = vchiq_connect_internal(state, instance); - - if (!ret) - instance->connected = 1; - - mutex_unlock(&state->mutex); - -failed: - dev_dbg(state->dev, "core: (%p): returning %d\n", instance, ret); - - return ret; -} -EXPORT_SYMBOL(vchiq_connect); - -static int -vchiq_add_service(struct vchiq_instance *instance, - const struct vchiq_service_params_kernel *params, - unsigned int *phandle) -{ - struct vchiq_state *state = instance->state; - struct vchiq_service *service = NULL; - int srvstate, ret; - - *phandle = VCHIQ_SERVICE_HANDLE_INVALID; - - srvstate = vchiq_is_connected(instance) - ? VCHIQ_SRVSTATE_LISTENING - : VCHIQ_SRVSTATE_HIDDEN; - - service = vchiq_add_service_internal(state, params, srvstate, instance, NULL); - - if (service) { - *phandle = service->handle; - ret = 0; - } else { - ret = -EINVAL; - } - - dev_dbg(state->dev, "core: (%p): returning %d\n", instance, ret); - - return ret; -} - -int -vchiq_open_service(struct vchiq_instance *instance, - const struct vchiq_service_params_kernel *params, - unsigned int *phandle) -{ - struct vchiq_state *state = instance->state; - struct vchiq_service *service = NULL; - int ret = -EINVAL; - - *phandle = VCHIQ_SERVICE_HANDLE_INVALID; - - if (!vchiq_is_connected(instance)) - goto failed; - - service = vchiq_add_service_internal(state, params, VCHIQ_SRVSTATE_OPENING, instance, NULL); - - if (service) { - *phandle = service->handle; - ret = vchiq_open_service_internal(service, current->pid); - if (ret) { - vchiq_remove_service(instance, service->handle); - *phandle = VCHIQ_SERVICE_HANDLE_INVALID; - } - } - -failed: - dev_dbg(state->dev, "core: (%p): returning %d\n", instance, ret); - - return ret; -} -EXPORT_SYMBOL(vchiq_open_service); - -int -vchiq_bulk_transmit(struct vchiq_instance *instance, unsigned int handle, const void *data, - unsigned int size, void *userdata, enum vchiq_bulk_mode mode) -{ - struct vchiq_bulk bulk_params = {}; - int ret; - - switch (mode) { - case VCHIQ_BULK_MODE_NOCALLBACK: - case VCHIQ_BULK_MODE_CALLBACK: - - bulk_params.offset = (void *)data; - bulk_params.mode = mode; - bulk_params.size = size; - bulk_params.cb_data = userdata; - bulk_params.dir = VCHIQ_BULK_TRANSMIT; - - ret = vchiq_bulk_xfer_callback(instance, handle, &bulk_params); - break; - case VCHIQ_BULK_MODE_BLOCKING: - bulk_params.offset = (void *)data; - bulk_params.mode = mode; - bulk_params.size = size; - bulk_params.dir = VCHIQ_BULK_TRANSMIT; - - ret = vchiq_blocking_bulk_transfer(instance, handle, &bulk_params); - break; - default: - return -EINVAL; - } - - return ret; -} -EXPORT_SYMBOL(vchiq_bulk_transmit); - -int vchiq_bulk_receive(struct vchiq_instance *instance, unsigned int handle, - void *data, unsigned int size, void *userdata, - enum vchiq_bulk_mode mode) -{ - struct vchiq_bulk bulk_params = {}; - int ret; - - switch (mode) { - case VCHIQ_BULK_MODE_NOCALLBACK: - case VCHIQ_BULK_MODE_CALLBACK: - - bulk_params.offset = (void *)data; - bulk_params.mode = mode; - bulk_params.size = size; - bulk_params.cb_data = userdata; - bulk_params.dir = VCHIQ_BULK_RECEIVE; - - ret = vchiq_bulk_xfer_callback(instance, handle, &bulk_params); - break; - case VCHIQ_BULK_MODE_BLOCKING: - bulk_params.offset = (void *)data; - bulk_params.mode = mode; - bulk_params.size = size; - bulk_params.dir = VCHIQ_BULK_RECEIVE; - - ret = vchiq_blocking_bulk_transfer(instance, handle, &bulk_params); - break; - default: - return -EINVAL; - } - - return ret; -} -EXPORT_SYMBOL(vchiq_bulk_receive); - -static int -vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_bulk *bulk_params) -{ - struct vchiq_service *service; - struct bulk_waiter_node *waiter = NULL, *iter; - int ret; - - service = find_service_by_handle(instance, handle); - if (!service) - return -EINVAL; - - vchiq_service_put(service); - - mutex_lock(&instance->bulk_waiter_list_mutex); - list_for_each_entry(iter, &instance->bulk_waiter_list, list) { - if (iter->pid == current->pid) { - list_del(&iter->list); - waiter = iter; - break; - } - } - mutex_unlock(&instance->bulk_waiter_list_mutex); - - if (waiter) { - struct vchiq_bulk *bulk = waiter->bulk_waiter.bulk; - - if (bulk) { - /* This thread has an outstanding bulk transfer. */ - /* FIXME: why compare a dma address to a pointer? */ - if ((bulk->dma_addr != (dma_addr_t)(uintptr_t)bulk_params->dma_addr) || - (bulk->size != bulk_params->size)) { - /* - * This is not a retry of the previous one. - * Cancel the signal when the transfer completes. - */ - spin_lock(&service->state->bulk_waiter_spinlock); - bulk->waiter = NULL; - spin_unlock(&service->state->bulk_waiter_spinlock); - } - } - } else { - waiter = kzalloc(sizeof(*waiter), GFP_KERNEL); - if (!waiter) - return -ENOMEM; - } - - bulk_params->waiter = &waiter->bulk_waiter; - - ret = vchiq_bulk_xfer_blocking(instance, handle, bulk_params); - if ((ret != -EAGAIN) || fatal_signal_pending(current) || !waiter->bulk_waiter.bulk) { - struct vchiq_bulk *bulk = waiter->bulk_waiter.bulk; - - if (bulk) { - /* Cancel the signal when the transfer completes. */ - spin_lock(&service->state->bulk_waiter_spinlock); - bulk->waiter = NULL; - spin_unlock(&service->state->bulk_waiter_spinlock); - } - kfree(waiter); - } else { - waiter->pid = current->pid; - mutex_lock(&instance->bulk_waiter_list_mutex); - list_add(&waiter->list, &instance->bulk_waiter_list); - mutex_unlock(&instance->bulk_waiter_list_mutex); - dev_dbg(instance->state->dev, "arm: saved bulk_waiter %p for pid %d\n", - waiter, current->pid); - } - - return ret; -} - -static int -add_completion(struct vchiq_instance *instance, enum vchiq_reason reason, - struct vchiq_header *header, struct user_service *user_service, - void *cb_data, void __user *cb_userdata) -{ - struct vchiq_completion_data_kernel *completion; - struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(instance->state->dev); - int insert; - - DEBUG_INITIALISE(mgmt->state.local); - - insert = instance->completion_insert; - while ((insert - instance->completion_remove) >= MAX_COMPLETIONS) { - /* Out of space - wait for the client */ - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - dev_dbg(instance->state->dev, "core: completion queue full\n"); - DEBUG_COUNT(COMPLETION_QUEUE_FULL_COUNT); - if (wait_for_completion_interruptible(&instance->remove_event)) { - dev_dbg(instance->state->dev, "arm: service_callback interrupted\n"); - return -EAGAIN; - } else if (instance->closing) { - dev_dbg(instance->state->dev, "arm: service_callback closing\n"); - return 0; - } - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - } - - completion = &instance->completions[insert & (MAX_COMPLETIONS - 1)]; - - completion->header = header; - completion->reason = reason; - /* N.B. service_userdata is updated while processing AWAIT_COMPLETION */ - completion->service_userdata = user_service->service; - completion->cb_data = cb_data; - completion->cb_userdata = cb_userdata; - - if (reason == VCHIQ_SERVICE_CLOSED) { - /* - * Take an extra reference, to be held until - * this CLOSED notification is delivered. - */ - vchiq_service_get(user_service->service); - if (instance->use_close_delivered) - user_service->close_pending = 1; - } - - /* - * A write barrier is needed here to ensure that the entire completion - * record is written out before the insert point. - */ - wmb(); - - if (reason == VCHIQ_MESSAGE_AVAILABLE) - user_service->message_available_pos = insert; - - insert++; - instance->completion_insert = insert; - - complete(&instance->insert_event); - - return 0; -} - -static int -service_single_message(struct vchiq_instance *instance, - enum vchiq_reason reason, struct vchiq_service *service, - void *cb_data, void __user *cb_userdata) -{ - struct user_service *user_service; - - user_service = (struct user_service *)service->base.userdata; - - dev_dbg(service->state->dev, "arm: msg queue full\n"); - /* - * If there is no MESSAGE_AVAILABLE in the completion - * queue, add one - */ - if ((user_service->message_available_pos - - instance->completion_remove) < 0) { - int ret; - - dev_dbg(instance->state->dev, - "arm: Inserting extra MESSAGE_AVAILABLE\n"); - ret = add_completion(instance, reason, NULL, user_service, - cb_data, cb_userdata); - if (ret) - return ret; - } - - if (wait_for_completion_interruptible(&user_service->remove_event)) { - dev_dbg(instance->state->dev, "arm: interrupted\n"); - return -EAGAIN; - } else if (instance->closing) { - dev_dbg(instance->state->dev, "arm: closing\n"); - return -EINVAL; - } - - return 0; -} - -int -service_callback(struct vchiq_instance *instance, enum vchiq_reason reason, - struct vchiq_header *header, unsigned int handle, - void *cb_data, void __user *cb_userdata) -{ - /* - * How do we ensure the callback goes to the right client? - * The service_user data points to a user_service record - * containing the original callback and the user state structure, which - * contains a circular buffer for completion records. - */ - struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(instance->state->dev); - struct user_service *user_service; - struct vchiq_service *service; - bool skip_completion = false; - - DEBUG_INITIALISE(mgmt->state.local); - - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - - rcu_read_lock(); - service = handle_to_service(instance, handle); - if (WARN_ON(!service)) { - rcu_read_unlock(); - return 0; - } - - user_service = (struct user_service *)service->base.userdata; - - if (instance->closing) { - rcu_read_unlock(); - return 0; - } - - /* - * As hopping around different synchronization mechanism, - * taking an extra reference results in simpler implementation. - */ - vchiq_service_get(service); - rcu_read_unlock(); - - dev_dbg(service->state->dev, - "arm: service %p(%d,%p), reason %d, header %p, instance %p, cb_data %p, cb_userdata %p\n", - user_service, service->localport, user_service->userdata, - reason, header, instance, cb_data, cb_userdata); - - if (header && user_service->is_vchi) { - spin_lock(&service->state->msg_queue_spinlock); - while (user_service->msg_insert == - (user_service->msg_remove + MSG_QUEUE_SIZE)) { - int ret; - - spin_unlock(&service->state->msg_queue_spinlock); - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - DEBUG_COUNT(MSG_QUEUE_FULL_COUNT); - - ret = service_single_message(instance, reason, service, - cb_data, cb_userdata); - if (ret) { - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - vchiq_service_put(service); - return ret; - } - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - spin_lock(&service->state->msg_queue_spinlock); - } - - user_service->msg_queue[user_service->msg_insert & - (MSG_QUEUE_SIZE - 1)] = header; - user_service->msg_insert++; - - /* - * If there is a thread waiting in DEQUEUE_MESSAGE, or if - * there is a MESSAGE_AVAILABLE in the completion queue then - * bypass the completion queue. - */ - if (((user_service->message_available_pos - - instance->completion_remove) >= 0) || - user_service->dequeue_pending) { - user_service->dequeue_pending = 0; - skip_completion = true; - } - - spin_unlock(&service->state->msg_queue_spinlock); - complete(&user_service->insert_event); - - header = NULL; - } - DEBUG_TRACE(SERVICE_CALLBACK_LINE); - vchiq_service_put(service); - - if (skip_completion) - return 0; - - return add_completion(instance, reason, header, user_service, - cb_data, cb_userdata); -} - -void vchiq_dump_platform_instances(struct vchiq_state *state, struct seq_file *f) -{ - int i; - - if (!vchiq_remote_initialised(state)) - return; - - /* - * There is no list of instances, so instead scan all services, - * marking those that have been dumped. - */ - - rcu_read_lock(); - for (i = 0; i < state->unused_service; i++) { - struct vchiq_service *service; - struct vchiq_instance *instance; - - service = rcu_dereference(state->services[i]); - if (!service || service->base.callback != service_callback) - continue; - - instance = service->instance; - if (instance) - instance->mark = 0; - } - rcu_read_unlock(); - - for (i = 0; i < state->unused_service; i++) { - struct vchiq_service *service; - struct vchiq_instance *instance; - - rcu_read_lock(); - service = rcu_dereference(state->services[i]); - if (!service || service->base.callback != service_callback) { - rcu_read_unlock(); - continue; - } - - instance = service->instance; - if (!instance || instance->mark) { - rcu_read_unlock(); - continue; - } - rcu_read_unlock(); - - seq_printf(f, "Instance %pK: pid %d,%s completions %d/%d\n", - instance, instance->pid, - instance->connected ? " connected, " : - "", - instance->completion_insert - - instance->completion_remove, - MAX_COMPLETIONS); - instance->mark = 1; - } -} - -void vchiq_dump_platform_service_state(struct seq_file *f, - struct vchiq_service *service) -{ - struct user_service *user_service = - (struct user_service *)service->base.userdata; - - seq_printf(f, " instance %pK", service->instance); - - if ((service->base.callback == service_callback) && user_service->is_vchi) { - seq_printf(f, ", %d/%d messages", - user_service->msg_insert - user_service->msg_remove, - MSG_QUEUE_SIZE); - - if (user_service->dequeue_pending) - seq_puts(f, " (dequeue pending)"); - } - - seq_puts(f, "\n"); -} - -/* - * Autosuspend related functionality - */ - -static int -vchiq_keepalive_vchiq_callback(struct vchiq_instance *instance, - enum vchiq_reason reason, - struct vchiq_header *header, - unsigned int service_user, - void *cb_data, void __user *cb_userdata) -{ - dev_err(instance->state->dev, "suspend: %s: callback reason %d\n", - __func__, reason); - return 0; -} - -static int -vchiq_keepalive_thread_func(void *v) -{ - struct vchiq_state *state = (struct vchiq_state *)v; - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - struct vchiq_instance *instance; - unsigned int ka_handle; - int ret; - - struct vchiq_service_params_kernel params = { - .fourcc = VCHIQ_MAKE_FOURCC('K', 'E', 'E', 'P'), - .callback = vchiq_keepalive_vchiq_callback, - .version = KEEPALIVE_VER, - .version_min = KEEPALIVE_VER_MIN - }; - - ret = vchiq_initialise(state, &instance); - if (ret) { - dev_err(state->dev, "suspend: %s: vchiq_initialise failed %d\n", __func__, ret); - goto exit; - } - - ret = vchiq_connect(instance); - if (ret) { - dev_err(state->dev, "suspend: %s: vchiq_connect failed %d\n", __func__, ret); - goto shutdown; - } - - ret = vchiq_add_service(instance, ¶ms, &ka_handle); - if (ret) { - dev_err(state->dev, "suspend: %s: vchiq_open_service failed %d\n", - __func__, ret); - goto shutdown; - } - - while (!kthread_should_stop()) { - long rc = 0, uc = 0; - - if (wait_for_completion_interruptible(&arm_state->ka_evt)) { - dev_dbg(state->dev, "suspend: %s: interrupted\n", __func__); - flush_signals(current); - continue; - } - - /* - * read and clear counters. Do release_count then use_count to - * prevent getting more releases than uses - */ - rc = atomic_xchg(&arm_state->ka_release_count, 0); - uc = atomic_xchg(&arm_state->ka_use_count, 0); - - /* - * Call use/release service the requisite number of times. - * Process use before release so use counts don't go negative - */ - while (uc--) { - atomic_inc(&arm_state->ka_use_ack_count); - ret = vchiq_use_service(instance, ka_handle); - if (ret) { - dev_err(state->dev, "suspend: %s: vchiq_use_service error %d\n", - __func__, ret); - } - } - while (rc--) { - ret = vchiq_release_service(instance, ka_handle); - if (ret) { - dev_err(state->dev, "suspend: %s: vchiq_release_service error %d\n", - __func__, ret); - } - } - } - -shutdown: - vchiq_shutdown(instance); -exit: - return 0; -} - -int -vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, - enum USE_TYPE_E use_type) -{ - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - int ret = 0; - char entity[64]; - int *entity_uc; - int local_uc; - - if (!arm_state) { - ret = -EINVAL; - goto out; - } - - if (use_type == USE_TYPE_VCHIQ) { - snprintf(entity, sizeof(entity), "VCHIQ: "); - entity_uc = &arm_state->peer_use_count; - } else if (service) { - snprintf(entity, sizeof(entity), "%p4cc:%03d", - &service->base.fourcc, - service->client_id); - entity_uc = &service->service_use_count; - } else { - dev_err(state->dev, "suspend: %s: null service ptr\n", __func__); - ret = -EINVAL; - goto out; - } - - write_lock_bh(&arm_state->susp_res_lock); - local_uc = ++arm_state->videocore_use_count; - ++(*entity_uc); - - dev_dbg(state->dev, "suspend: %s count %d, state count %d\n", - entity, *entity_uc, local_uc); - - write_unlock_bh(&arm_state->susp_res_lock); - - if (!ret) { - int ret = 0; - long ack_cnt = atomic_xchg(&arm_state->ka_use_ack_count, 0); - - while (ack_cnt && !ret) { - /* Send the use notify to videocore */ - ret = vchiq_send_remote_use_active(state); - if (!ret) - ack_cnt--; - else - atomic_add(ack_cnt, &arm_state->ka_use_ack_count); - } - } - -out: - dev_dbg(state->dev, "suspend: exit %d\n", ret); - return ret; -} - -int -vchiq_release_internal(struct vchiq_state *state, struct vchiq_service *service) -{ - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - int ret = 0; - char entity[64]; - int *entity_uc; - - if (!arm_state) { - ret = -EINVAL; - goto out; - } - - if (service) { - snprintf(entity, sizeof(entity), "%p4cc:%03d", - &service->base.fourcc, - service->client_id); - entity_uc = &service->service_use_count; - } else { - snprintf(entity, sizeof(entity), "PEER: "); - entity_uc = &arm_state->peer_use_count; - } - - write_lock_bh(&arm_state->susp_res_lock); - if (!arm_state->videocore_use_count || !(*entity_uc)) { - WARN_ON(!arm_state->videocore_use_count); - WARN_ON(!(*entity_uc)); - ret = -EINVAL; - goto unlock; - } - --arm_state->videocore_use_count; - --(*entity_uc); - - dev_dbg(state->dev, "suspend: %s count %d, state count %d\n", - entity, *entity_uc, arm_state->videocore_use_count); - -unlock: - write_unlock_bh(&arm_state->susp_res_lock); - -out: - dev_dbg(state->dev, "suspend: exit %d\n", ret); - return ret; -} - -void -vchiq_on_remote_use(struct vchiq_state *state) -{ - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - - atomic_inc(&arm_state->ka_use_count); - complete(&arm_state->ka_evt); -} - -void -vchiq_on_remote_release(struct vchiq_state *state) -{ - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - - atomic_inc(&arm_state->ka_release_count); - complete(&arm_state->ka_evt); -} - -int -vchiq_use_service_internal(struct vchiq_service *service) -{ - return vchiq_use_internal(service->state, service, USE_TYPE_SERVICE); -} - -int -vchiq_release_service_internal(struct vchiq_service *service) -{ - return vchiq_release_internal(service->state, service); -} - -struct vchiq_debugfs_node * -vchiq_instance_get_debugfs_node(struct vchiq_instance *instance) -{ - return &instance->debugfs_node; -} - -int -vchiq_instance_get_use_count(struct vchiq_instance *instance) -{ - struct vchiq_service *service; - int use_count = 0, i; - - i = 0; - rcu_read_lock(); - while ((service = __next_service_by_instance(instance->state, - instance, &i))) - use_count += service->service_use_count; - rcu_read_unlock(); - return use_count; -} - -int -vchiq_instance_get_pid(struct vchiq_instance *instance) -{ - return instance->pid; -} - -int -vchiq_instance_get_trace(struct vchiq_instance *instance) -{ - return instance->trace; -} - -void -vchiq_instance_set_trace(struct vchiq_instance *instance, int trace) -{ - struct vchiq_service *service; - int i; - - i = 0; - rcu_read_lock(); - while ((service = __next_service_by_instance(instance->state, - instance, &i))) - service->trace = trace; - rcu_read_unlock(); - instance->trace = (trace != 0); -} - -int -vchiq_use_service(struct vchiq_instance *instance, unsigned int handle) -{ - int ret = -EINVAL; - struct vchiq_service *service = find_service_by_handle(instance, handle); - - if (service) { - ret = vchiq_use_internal(service->state, service, USE_TYPE_SERVICE); - vchiq_service_put(service); - } - return ret; -} -EXPORT_SYMBOL(vchiq_use_service); - -int -vchiq_release_service(struct vchiq_instance *instance, unsigned int handle) -{ - int ret = -EINVAL; - struct vchiq_service *service = find_service_by_handle(instance, handle); - - if (service) { - ret = vchiq_release_internal(service->state, service); - vchiq_service_put(service); - } - return ret; -} -EXPORT_SYMBOL(vchiq_release_service); - -struct service_data_struct { - int fourcc; - int clientid; - int use_count; -}; - -void -vchiq_dump_service_use_state(struct vchiq_state *state) -{ - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - struct service_data_struct *service_data; - int i, found = 0; - /* - * If there's more than 64 services, only dump ones with - * non-zero counts - */ - int only_nonzero = 0; - static const char *nz = "<-- preventing suspend"; - - int peer_count; - int vc_use_count; - int active_services; - - if (!arm_state) - return; - - service_data = kmalloc_array(MAX_SERVICES, sizeof(*service_data), - GFP_KERNEL); - if (!service_data) - return; - - read_lock_bh(&arm_state->susp_res_lock); - peer_count = arm_state->peer_use_count; - vc_use_count = arm_state->videocore_use_count; - active_services = state->unused_service; - if (active_services > MAX_SERVICES) - only_nonzero = 1; - - rcu_read_lock(); - for (i = 0; i < active_services; i++) { - struct vchiq_service *service_ptr = - rcu_dereference(state->services[i]); - - if (!service_ptr) - continue; - - if (only_nonzero && !service_ptr->service_use_count) - continue; - - if (service_ptr->srvstate == VCHIQ_SRVSTATE_FREE) - continue; - - service_data[found].fourcc = service_ptr->base.fourcc; - service_data[found].clientid = service_ptr->client_id; - service_data[found].use_count = service_ptr->service_use_count; - found++; - if (found >= MAX_SERVICES) - break; - } - rcu_read_unlock(); - - read_unlock_bh(&arm_state->susp_res_lock); - - if (only_nonzero) - dev_warn(state->dev, - "suspend: Too many active services (%d). Only dumping up to first %d services with non-zero use-count\n", - active_services, found); - - for (i = 0; i < found; i++) { - dev_warn(state->dev, - "suspend: %p4cc:%d service count %d %s\n", - &service_data[i].fourcc, - service_data[i].clientid, service_data[i].use_count, - service_data[i].use_count ? nz : ""); - } - dev_warn(state->dev, "suspend: VCHIQ use count %d\n", peer_count); - dev_warn(state->dev, "suspend: Overall vchiq instance use count %d\n", vc_use_count); - - kfree(service_data); -} - -int -vchiq_check_service(struct vchiq_service *service) -{ - struct vchiq_arm_state *arm_state; - int ret = -EINVAL; - - if (!service || !service->state) - goto out; - - arm_state = vchiq_platform_get_arm_state(service->state); - - read_lock_bh(&arm_state->susp_res_lock); - if (service->service_use_count) - ret = 0; - read_unlock_bh(&arm_state->susp_res_lock); - - if (ret) { - dev_err(service->state->dev, - "suspend: %s: %p4cc:%d service count %d, state count %d\n", - __func__, &service->base.fourcc, service->client_id, - service->service_use_count, arm_state->videocore_use_count); - vchiq_dump_service_use_state(service->state); - } -out: - return ret; -} - -void vchiq_platform_conn_state_changed(struct vchiq_state *state, - enum vchiq_connstate oldstate, - enum vchiq_connstate newstate) -{ - struct vchiq_arm_state *arm_state = vchiq_platform_get_arm_state(state); - char threadname[16]; - - dev_dbg(state->dev, "suspend: %d: %s->%s\n", - state->id, get_conn_state_name(oldstate), get_conn_state_name(newstate)); - if (state->conn_state != VCHIQ_CONNSTATE_CONNECTED) - return; - - write_lock_bh(&arm_state->susp_res_lock); - if (arm_state->first_connect) { - write_unlock_bh(&arm_state->susp_res_lock); - return; - } - - arm_state->first_connect = 1; - write_unlock_bh(&arm_state->susp_res_lock); - snprintf(threadname, sizeof(threadname), "vchiq-keep/%d", - state->id); - arm_state->ka_thread = kthread_create(&vchiq_keepalive_thread_func, - (void *)state, - threadname); - if (IS_ERR(arm_state->ka_thread)) { - dev_err(state->dev, "suspend: Couldn't create thread %s\n", - threadname); - } else { - wake_up_process(arm_state->ka_thread); - } -} - -static const struct of_device_id vchiq_of_match[] = { - { .compatible = "brcm,bcm2835-vchiq", .data = &bcm2835_info }, - { .compatible = "brcm,bcm2836-vchiq", .data = &bcm2836_info }, - {}, -}; -MODULE_DEVICE_TABLE(of, vchiq_of_match); - -static int vchiq_probe(struct platform_device *pdev) -{ - const struct vchiq_platform_info *info; - struct vchiq_drv_mgmt *mgmt; - int ret; - - info = of_device_get_match_data(&pdev->dev); - if (!info) - return -EINVAL; - - struct device_node *fw_node __free(device_node) = - of_find_compatible_node(NULL, NULL, "raspberrypi,bcm2835-firmware"); - if (!fw_node) { - dev_err(&pdev->dev, "Missing firmware node\n"); - return -ENOENT; - } - - mgmt = devm_kzalloc(&pdev->dev, sizeof(*mgmt), GFP_KERNEL); - if (!mgmt) - return -ENOMEM; - - mgmt->fw = devm_rpi_firmware_get(&pdev->dev, fw_node); - if (!mgmt->fw) - return -EPROBE_DEFER; - - mgmt->info = info; - platform_set_drvdata(pdev, mgmt); - - ret = vchiq_platform_init(pdev, &mgmt->state); - if (ret) { - dev_err(&pdev->dev, "arm: Could not initialize vchiq platform\n"); - return ret; - } - - dev_dbg(&pdev->dev, "arm: platform initialised - version %d (min %d)\n", - VCHIQ_VERSION, VCHIQ_VERSION_MIN); - - /* - * Simply exit on error since the function handles cleanup in - * cases of failure. - */ - ret = vchiq_register_chrdev(&pdev->dev); - if (ret) { - dev_err(&pdev->dev, "arm: Failed to initialize vchiq cdev\n"); - vchiq_platform_uninit(mgmt); - return ret; - } - - vchiq_debugfs_init(&mgmt->state); - - bcm2835_audio = vchiq_device_register(&pdev->dev, "bcm2835-audio"); - bcm2835_camera = vchiq_device_register(&pdev->dev, "bcm2835-camera"); - - return 0; -} - -static void vchiq_remove(struct platform_device *pdev) -{ - struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(&pdev->dev); - - vchiq_device_unregister(bcm2835_audio); - vchiq_device_unregister(bcm2835_camera); - vchiq_debugfs_deinit(); - vchiq_deregister_chrdev(); - vchiq_platform_uninit(mgmt); -} - -static struct platform_driver vchiq_driver = { - .driver = { - .name = "bcm2835_vchiq", - .of_match_table = vchiq_of_match, - }, - .probe = vchiq_probe, - .remove = vchiq_remove, -}; - -static int __init vchiq_driver_init(void) -{ - int ret; - - ret = bus_register(&vchiq_bus_type); - if (ret) { - pr_err("Failed to register %s\n", vchiq_bus_type.name); - return ret; - } - - ret = platform_driver_register(&vchiq_driver); - if (ret) { - pr_err("Failed to register vchiq driver\n"); - bus_unregister(&vchiq_bus_type); - } - - return ret; -} -module_init(vchiq_driver_init); - -static void __exit vchiq_driver_exit(void) -{ - bus_unregister(&vchiq_bus_type); - platform_driver_unregister(&vchiq_driver); -} -module_exit(vchiq_driver_exit); - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_DESCRIPTION("Videocore VCHIQ driver"); -MODULE_AUTHOR("Broadcom Corporation"); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h deleted file mode 100644 index e32b02f99024..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h +++ /dev/null @@ -1,164 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* - * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. - * Copyright (c) 2010-2012 Broadcom. All rights reserved. - */ - -#ifndef VCHIQ_ARM_H -#define VCHIQ_ARM_H - -#include <linux/mutex.h> -#include <linux/platform_device.h> -#include <linux/semaphore.h> -#include <linux/atomic.h> -#include "vchiq_core.h" -#include "vchiq_debugfs.h" - -/* Some per-instance constants */ -#define MAX_COMPLETIONS 128 -#define MAX_SERVICES 64 -#define MAX_ELEMENTS 8 -#define MSG_QUEUE_SIZE 128 - -#define VCHIQ_DRV_MAX_CALLBACKS 10 - -struct rpi_firmware; -struct vchiq_device; - -enum USE_TYPE_E { - USE_TYPE_SERVICE, - USE_TYPE_VCHIQ -}; - -struct vchiq_platform_info { - unsigned int cache_line_size; -}; - -struct vchiq_drv_mgmt { - struct rpi_firmware *fw; - const struct vchiq_platform_info *info; - - bool connected; - int num_deferred_callbacks; - /* Protects connected and num_deferred_callbacks */ - struct mutex connected_mutex; - - void (*deferred_callback[VCHIQ_DRV_MAX_CALLBACKS])(void); - - struct semaphore free_fragments_sema; - struct semaphore free_fragments_mutex; - char *fragments_base; - char *free_fragments; - unsigned int fragments_size; - - void __iomem *regs; - - struct vchiq_state state; -}; - -struct user_service { - struct vchiq_service *service; - void __user *userdata; - struct vchiq_instance *instance; - char is_vchi; - char dequeue_pending; - char close_pending; - int message_available_pos; - int msg_insert; - int msg_remove; - struct completion insert_event; - struct completion remove_event; - struct completion close_event; - struct vchiq_header *msg_queue[MSG_QUEUE_SIZE]; -}; - -struct bulk_waiter_node { - struct bulk_waiter bulk_waiter; - int pid; - struct list_head list; -}; - -struct vchiq_instance { - struct vchiq_state *state; - struct vchiq_completion_data_kernel completions[MAX_COMPLETIONS]; - int completion_insert; - int completion_remove; - struct completion insert_event; - struct completion remove_event; - struct mutex completion_mutex; - - int connected; - int closing; - int pid; - int mark; - int use_close_delivered; - int trace; - - struct list_head bulk_waiter_list; - struct mutex bulk_waiter_list_mutex; - - struct vchiq_debugfs_node debugfs_node; -}; - -int -vchiq_use_service(struct vchiq_instance *instance, unsigned int handle); - -extern int -vchiq_release_service(struct vchiq_instance *instance, unsigned int handle); - -extern int -vchiq_check_service(struct vchiq_service *service); - -extern void -vchiq_dump_service_use_state(struct vchiq_state *state); - -extern int -vchiq_use_internal(struct vchiq_state *state, struct vchiq_service *service, - enum USE_TYPE_E use_type); -extern int -vchiq_release_internal(struct vchiq_state *state, - struct vchiq_service *service); - -extern struct vchiq_debugfs_node * -vchiq_instance_get_debugfs_node(struct vchiq_instance *instance); - -extern int -vchiq_instance_get_use_count(struct vchiq_instance *instance); - -extern int -vchiq_instance_get_pid(struct vchiq_instance *instance); - -extern int -vchiq_instance_get_trace(struct vchiq_instance *instance); - -extern void -vchiq_instance_set_trace(struct vchiq_instance *instance, int trace); - -extern void -vchiq_add_connected_callback(struct vchiq_device *device, - void (*callback)(void)); - -#if IS_ENABLED(CONFIG_VCHIQ_CDEV) - -extern void -vchiq_deregister_chrdev(void); - -extern int -vchiq_register_chrdev(struct device *parent); - -#else - -static inline void vchiq_deregister_chrdev(void) { } -static inline int vchiq_register_chrdev(struct device *parent) { return 0; } - -#endif /* IS_ENABLED(CONFIG_VCHIQ_CDEV) */ - -extern int -service_callback(struct vchiq_instance *vchiq_instance, enum vchiq_reason reason, - struct vchiq_header *header, unsigned int handle, - void *cb_data, void __user *cb_userdata); - -extern void -free_bulk_waiter(struct vchiq_instance *instance); - -#endif /* VCHIQ_ARM_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.c deleted file mode 100644 index 41ece91ab88a..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.c +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * vchiq_device.c - VCHIQ generic device and bus-type - * - * Copyright (c) 2023 Ideas On Board Oy - */ - -#include <linux/device/bus.h> -#include <linux/dma-mapping.h> -#include <linux/of_device.h> -#include <linux/slab.h> -#include <linux/string.h> - -#include "vchiq_arm.h" -#include "vchiq_bus.h" - -static int vchiq_bus_type_match(struct device *dev, const struct device_driver *drv) -{ - if (dev->bus == &vchiq_bus_type && - strcmp(dev_name(dev), drv->name) == 0) - return true; - - return false; -} - -static int vchiq_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) -{ - const struct vchiq_device *device = container_of_const(dev, struct vchiq_device, dev); - - return add_uevent_var(env, "MODALIAS=vchiq:%s", dev_name(&device->dev)); -} - -static int vchiq_bus_probe(struct device *dev) -{ - struct vchiq_device *device = to_vchiq_device(dev); - struct vchiq_driver *driver = to_vchiq_driver(dev->driver); - - return driver->probe(device); -} - -static void vchiq_bus_remove(struct device *dev) -{ - struct vchiq_device *device = to_vchiq_device(dev); - struct vchiq_driver *driver = to_vchiq_driver(dev->driver); - - if (driver->remove) - driver->remove(device); -} - -const struct bus_type vchiq_bus_type = { - .name = "vchiq-bus", - .match = vchiq_bus_type_match, - .uevent = vchiq_bus_uevent, - .probe = vchiq_bus_probe, - .remove = vchiq_bus_remove, -}; - -static void vchiq_device_release(struct device *dev) -{ - struct vchiq_device *device = to_vchiq_device(dev); - - kfree(device); -} - -struct vchiq_device * -vchiq_device_register(struct device *parent, const char *name) -{ - struct vchiq_device *device; - int ret; - - device = kzalloc(sizeof(*device), GFP_KERNEL); - if (!device) - return NULL; - - device->dev.init_name = name; - device->dev.parent = parent; - device->dev.bus = &vchiq_bus_type; - device->dev.dma_mask = &device->dev.coherent_dma_mask; - device->dev.release = vchiq_device_release; - - device->drv_mgmt = dev_get_drvdata(parent); - - of_dma_configure(&device->dev, parent->of_node, true); - - ret = device_register(&device->dev); - if (ret) { - dev_err(parent, "Cannot register %s: %d\n", name, ret); - put_device(&device->dev); - return NULL; - } - - return device; -} - -void vchiq_device_unregister(struct vchiq_device *vchiq_dev) -{ - device_unregister(&vchiq_dev->dev); -} - -int vchiq_driver_register(struct vchiq_driver *vchiq_drv) -{ - vchiq_drv->driver.bus = &vchiq_bus_type; - - return driver_register(&vchiq_drv->driver); -} -EXPORT_SYMBOL_GPL(vchiq_driver_register); - -void vchiq_driver_unregister(struct vchiq_driver *vchiq_drv) -{ - driver_unregister(&vchiq_drv->driver); -} -EXPORT_SYMBOL_GPL(vchiq_driver_unregister); diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.h deleted file mode 100644 index 9de179b39f85..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_bus.h +++ /dev/null @@ -1,60 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) 2023 Ideas On Board Oy - */ - -#ifndef _VCHIQ_DEVICE_H -#define _VCHIQ_DEVICE_H - -#include <linux/device.h> -#include <linux/mod_devicetable.h> - -struct vchiq_drv_mgmt; - -struct vchiq_device { - struct device dev; - struct vchiq_drv_mgmt *drv_mgmt; -}; - -struct vchiq_driver { - int (*probe)(struct vchiq_device *device); - void (*remove)(struct vchiq_device *device); - int (*resume)(struct vchiq_device *device); - int (*suspend)(struct vchiq_device *device, - pm_message_t state); - - const struct vchiq_device_id *id_table; - struct device_driver driver; -}; - -static inline struct vchiq_device *to_vchiq_device(struct device *d) -{ - return container_of(d, struct vchiq_device, dev); -} - -static inline struct vchiq_driver *to_vchiq_driver(struct device_driver *d) -{ - return container_of(d, struct vchiq_driver, driver); -} - -extern const struct bus_type vchiq_bus_type; - -struct vchiq_device * -vchiq_device_register(struct device *parent, const char *name); -void vchiq_device_unregister(struct vchiq_device *dev); - -int vchiq_driver_register(struct vchiq_driver *vchiq_drv); -void vchiq_driver_unregister(struct vchiq_driver *vchiq_drv); - -/** - * module_vchiq_driver() - Helper macro for registering a vchiq driver - * @__vchiq_driver: vchiq driver struct - * - * Helper macro for vchiq drivers which do not do anything special in - * module init/exit. This eliminates a lot of boilerplate. Each module may only - * use this macro once, and calling it replaces module_init() and module_exit() - */ -#define module_vchiq_driver(__vchiq_driver) \ - module_driver(__vchiq_driver, vchiq_driver_register, vchiq_driver_unregister) - -#endif /* _VCHIQ_DEVICE_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h deleted file mode 100644 index a16d0299996c..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_cfg.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2014 Broadcom. All rights reserved. */ - -#ifndef VCHIQ_CFG_H -#define VCHIQ_CFG_H - -#define VCHIQ_MAGIC VCHIQ_MAKE_FOURCC('V', 'C', 'H', 'I') -/* The version of VCHIQ - change with any non-trivial change */ -#define VCHIQ_VERSION 8 -/* - * The minimum compatible version - update to match VCHIQ_VERSION with any - * incompatible change - */ -#define VCHIQ_VERSION_MIN 3 - -/* The version that introduced the VCHIQ_IOC_LIB_VERSION ioctl */ -#define VCHIQ_VERSION_LIB_VERSION 7 - -/* The version that introduced the VCHIQ_IOC_CLOSE_DELIVERED ioctl */ -#define VCHIQ_VERSION_CLOSE_DELIVERED 7 - -/* The version that made it safe to use SYNCHRONOUS mode */ -#define VCHIQ_VERSION_SYNCHRONOUS_MODE 8 - -#define VCHIQ_MAX_STATES 1 -#define VCHIQ_MAX_SERVICES 4096 -#define VCHIQ_MAX_SLOTS 128 -#define VCHIQ_MAX_SLOTS_PER_SIDE 64 - -#define VCHIQ_NUM_CURRENT_BULKS 32 -#define VCHIQ_NUM_SERVICE_BULKS 4 - -#ifndef VCHIQ_ENABLE_DEBUG -#define VCHIQ_ENABLE_DEBUG 1 -#endif - -#ifndef VCHIQ_ENABLE_STATS -#define VCHIQ_ENABLE_STATS 1 -#endif - -#endif /* VCHIQ_CFG_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c deleted file mode 100644 index e2cac0898b8f..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c +++ /dev/null @@ -1,4016 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#include <linux/types.h> -#include <linux/completion.h> -#include <linux/mutex.h> -#include <linux/bitops.h> -#include <linux/io.h> -#include <linux/highmem.h> -#include <linux/kthread.h> -#include <linux/wait.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/kref.h> -#include <linux/rcupdate.h> -#include <linux/sched/signal.h> - -#include "vchiq_arm.h" -#include "vchiq_core.h" - -#define VCHIQ_SLOT_HANDLER_STACK 8192 - -#define VCHIQ_MSG_PADDING 0 /* - */ -#define VCHIQ_MSG_CONNECT 1 /* - */ -#define VCHIQ_MSG_OPEN 2 /* + (srcport, -), fourcc, client_id */ -#define VCHIQ_MSG_OPENACK 3 /* + (srcport, dstport) */ -#define VCHIQ_MSG_CLOSE 4 /* + (srcport, dstport) */ -#define VCHIQ_MSG_DATA 5 /* + (srcport, dstport) */ -#define VCHIQ_MSG_BULK_RX 6 /* + (srcport, dstport), data, size */ -#define VCHIQ_MSG_BULK_TX 7 /* + (srcport, dstport), data, size */ -#define VCHIQ_MSG_BULK_RX_DONE 8 /* + (srcport, dstport), actual */ -#define VCHIQ_MSG_BULK_TX_DONE 9 /* + (srcport, dstport), actual */ -#define VCHIQ_MSG_PAUSE 10 /* - */ -#define VCHIQ_MSG_RESUME 11 /* - */ -#define VCHIQ_MSG_REMOTE_USE 12 /* - */ -#define VCHIQ_MSG_REMOTE_RELEASE 13 /* - */ -#define VCHIQ_MSG_REMOTE_USE_ACTIVE 14 /* - */ - -#define TYPE_SHIFT 24 - -#define VCHIQ_PORT_MAX (VCHIQ_MAX_SERVICES - 1) -#define VCHIQ_PORT_FREE 0x1000 -#define VCHIQ_PORT_IS_VALID(port) ((port) < VCHIQ_PORT_FREE) -#define VCHIQ_MAKE_MSG(type, srcport, dstport) \ - (((type) << TYPE_SHIFT) | ((srcport) << 12) | ((dstport) << 0)) -#define VCHIQ_MSG_TYPE(msgid) ((unsigned int)(msgid) >> TYPE_SHIFT) -#define VCHIQ_MSG_SRCPORT(msgid) \ - ((unsigned short)(((unsigned int)(msgid) >> 12) & 0xfff)) -#define VCHIQ_MSG_DSTPORT(msgid) \ - ((unsigned short)(msgid) & 0xfff) - -#define MAKE_CONNECT (VCHIQ_MSG_CONNECT << TYPE_SHIFT) -#define MAKE_OPEN(srcport) \ - ((VCHIQ_MSG_OPEN << TYPE_SHIFT) | ((srcport) << 12)) -#define MAKE_OPENACK(srcport, dstport) \ - ((VCHIQ_MSG_OPENACK << TYPE_SHIFT) | ((srcport) << 12) | ((dstport) << 0)) -#define MAKE_CLOSE(srcport, dstport) \ - ((VCHIQ_MSG_CLOSE << TYPE_SHIFT) | ((srcport) << 12) | ((dstport) << 0)) -#define MAKE_DATA(srcport, dstport) \ - ((VCHIQ_MSG_DATA << TYPE_SHIFT) | ((srcport) << 12) | ((dstport) << 0)) -#define MAKE_PAUSE (VCHIQ_MSG_PAUSE << TYPE_SHIFT) -#define MAKE_RESUME (VCHIQ_MSG_RESUME << TYPE_SHIFT) -#define MAKE_REMOTE_USE (VCHIQ_MSG_REMOTE_USE << TYPE_SHIFT) -#define MAKE_REMOTE_USE_ACTIVE (VCHIQ_MSG_REMOTE_USE_ACTIVE << TYPE_SHIFT) - -#define PAGELIST_WRITE 0 -#define PAGELIST_READ 1 -#define PAGELIST_READ_WITH_FRAGMENTS 2 - -#define BELL2 0x08 - -/* Ensure the fields are wide enough */ -static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX)) == 0); -static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0); -static_assert((unsigned int)VCHIQ_PORT_MAX < (unsigned int)VCHIQ_PORT_FREE); - -#define VCHIQ_MSGID_PADDING VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING, 0, 0) -#define VCHIQ_MSGID_CLAIMED 0x40000000 - -#define VCHIQ_FOURCC_INVALID 0x00000000 -#define VCHIQ_FOURCC_IS_LEGAL(fourcc) ((fourcc) != VCHIQ_FOURCC_INVALID) - -#define VCHIQ_BULK_ACTUAL_ABORTED -1 - -#if VCHIQ_ENABLE_STATS -#define VCHIQ_STATS_INC(state, stat) (state->stats. stat++) -#define VCHIQ_SERVICE_STATS_INC(service, stat) (service->stats. stat++) -#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) \ - (service->stats. stat += addend) -#else -#define VCHIQ_STATS_INC(state, stat) ((void)0) -#define VCHIQ_SERVICE_STATS_INC(service, stat) ((void)0) -#define VCHIQ_SERVICE_STATS_ADD(service, stat, addend) ((void)0) -#endif - -#define HANDLE_STATE_SHIFT 12 - -#define SLOT_INFO_FROM_INDEX(state, index) (state->slot_info + (index)) -#define SLOT_DATA_FROM_INDEX(state, index) (state->slot_data + (index)) -#define SLOT_INDEX_FROM_DATA(state, data) \ - (((unsigned int)((char *)data - (char *)state->slot_data)) / \ - VCHIQ_SLOT_SIZE) -#define SLOT_INDEX_FROM_INFO(state, info) \ - ((unsigned int)(info - state->slot_info)) -#define SLOT_QUEUE_INDEX_FROM_POS(pos) \ - ((int)((unsigned int)(pos) / VCHIQ_SLOT_SIZE)) -#define SLOT_QUEUE_INDEX_FROM_POS_MASKED(pos) \ - (SLOT_QUEUE_INDEX_FROM_POS(pos) & VCHIQ_SLOT_QUEUE_MASK) - -#define BULK_INDEX(x) ((x) & (VCHIQ_NUM_SERVICE_BULKS - 1)) - -#define NO_CLOSE_RECVD 0 -#define CLOSE_RECVD 1 - -#define NO_RETRY_POLL 0 -#define RETRY_POLL 1 - -struct vchiq_open_payload { - int fourcc; - int client_id; - short version; - short version_min; -}; - -struct vchiq_openack_payload { - short version; -}; - -enum { - QMFLAGS_IS_BLOCKING = BIT(0), - QMFLAGS_NO_MUTEX_LOCK = BIT(1), - QMFLAGS_NO_MUTEX_UNLOCK = BIT(2) -}; - -enum { - VCHIQ_POLL_TERMINATE, - VCHIQ_POLL_REMOVE, - VCHIQ_POLL_TXNOTIFY, - VCHIQ_POLL_RXNOTIFY, - VCHIQ_POLL_COUNT -}; - -/* we require this for consistency between endpoints */ -static_assert(sizeof(struct vchiq_header) == 8); -static_assert(VCHIQ_VERSION >= VCHIQ_VERSION_MIN); - -static inline void check_sizes(void) -{ - BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_SLOT_SIZE); - BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_MAX_SLOTS); - BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_MAX_SLOTS_PER_SIDE); - BUILD_BUG_ON_NOT_POWER_OF_2(sizeof(struct vchiq_header)); - BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_NUM_CURRENT_BULKS); - BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_NUM_SERVICE_BULKS); - BUILD_BUG_ON_NOT_POWER_OF_2(VCHIQ_MAX_SERVICES); -} - -static unsigned int handle_seq; - -static const char *const srvstate_names[] = { - "FREE", - "HIDDEN", - "LISTENING", - "OPENING", - "OPEN", - "OPENSYNC", - "CLOSESENT", - "CLOSERECVD", - "CLOSEWAIT", - "CLOSED" -}; - -static const char *const reason_names[] = { - "SERVICE_OPENED", - "SERVICE_CLOSED", - "MESSAGE_AVAILABLE", - "BULK_TRANSMIT_DONE", - "BULK_RECEIVE_DONE", - "BULK_TRANSMIT_ABORTED", - "BULK_RECEIVE_ABORTED" -}; - -static const char *const conn_state_names[] = { - "DISCONNECTED", - "CONNECTING", - "CONNECTED", - "PAUSING", - "PAUSE_SENT", - "PAUSED", - "RESUMING", - "PAUSE_TIMEOUT", - "RESUME_TIMEOUT" -}; - -static void -release_message_sync(struct vchiq_state *state, struct vchiq_header *header); - -static const char *msg_type_str(unsigned int msg_type) -{ - switch (msg_type) { - case VCHIQ_MSG_PADDING: return "PADDING"; - case VCHIQ_MSG_CONNECT: return "CONNECT"; - case VCHIQ_MSG_OPEN: return "OPEN"; - case VCHIQ_MSG_OPENACK: return "OPENACK"; - case VCHIQ_MSG_CLOSE: return "CLOSE"; - case VCHIQ_MSG_DATA: return "DATA"; - case VCHIQ_MSG_BULK_RX: return "BULK_RX"; - case VCHIQ_MSG_BULK_TX: return "BULK_TX"; - case VCHIQ_MSG_BULK_RX_DONE: return "BULK_RX_DONE"; - case VCHIQ_MSG_BULK_TX_DONE: return "BULK_TX_DONE"; - case VCHIQ_MSG_PAUSE: return "PAUSE"; - case VCHIQ_MSG_RESUME: return "RESUME"; - case VCHIQ_MSG_REMOTE_USE: return "REMOTE_USE"; - case VCHIQ_MSG_REMOTE_RELEASE: return "REMOTE_RELEASE"; - case VCHIQ_MSG_REMOTE_USE_ACTIVE: return "REMOTE_USE_ACTIVE"; - } - return "???"; -} - -static inline void -set_service_state(struct vchiq_service *service, int newstate) -{ - dev_dbg(service->state->dev, "core: %d: srv:%d %s->%s\n", - service->state->id, service->localport, - srvstate_names[service->srvstate], - srvstate_names[newstate]); - service->srvstate = newstate; -} - -struct vchiq_service *handle_to_service(struct vchiq_instance *instance, unsigned int handle) -{ - int idx = handle & (VCHIQ_MAX_SERVICES - 1); - - return rcu_dereference(instance->state->services[idx]); -} - -struct vchiq_service * -find_service_by_handle(struct vchiq_instance *instance, unsigned int handle) -{ - struct vchiq_service *service; - - rcu_read_lock(); - service = handle_to_service(instance, handle); - if (service && service->srvstate != VCHIQ_SRVSTATE_FREE && - service->handle == handle && - kref_get_unless_zero(&service->ref_count)) { - service = rcu_pointer_handoff(service); - rcu_read_unlock(); - return service; - } - rcu_read_unlock(); - dev_dbg(instance->state->dev, "core: Invalid service handle 0x%x\n", handle); - return NULL; -} - -struct vchiq_service * -find_service_by_port(struct vchiq_state *state, unsigned int localport) -{ - if (localport <= VCHIQ_PORT_MAX) { - struct vchiq_service *service; - - rcu_read_lock(); - service = rcu_dereference(state->services[localport]); - if (service && service->srvstate != VCHIQ_SRVSTATE_FREE && - kref_get_unless_zero(&service->ref_count)) { - service = rcu_pointer_handoff(service); - rcu_read_unlock(); - return service; - } - rcu_read_unlock(); - } - dev_dbg(state->dev, "core: Invalid port %u\n", localport); - return NULL; -} - -struct vchiq_service * -find_service_for_instance(struct vchiq_instance *instance, unsigned int handle) -{ - struct vchiq_service *service; - - rcu_read_lock(); - service = handle_to_service(instance, handle); - if (service && service->srvstate != VCHIQ_SRVSTATE_FREE && - service->handle == handle && - service->instance == instance && - kref_get_unless_zero(&service->ref_count)) { - service = rcu_pointer_handoff(service); - rcu_read_unlock(); - return service; - } - rcu_read_unlock(); - dev_dbg(instance->state->dev, "core: Invalid service handle 0x%x\n", handle); - return NULL; -} - -struct vchiq_service * -find_closed_service_for_instance(struct vchiq_instance *instance, unsigned int handle) -{ - struct vchiq_service *service; - - rcu_read_lock(); - service = handle_to_service(instance, handle); - if (service && - (service->srvstate == VCHIQ_SRVSTATE_FREE || - service->srvstate == VCHIQ_SRVSTATE_CLOSED) && - service->handle == handle && - service->instance == instance && - kref_get_unless_zero(&service->ref_count)) { - service = rcu_pointer_handoff(service); - rcu_read_unlock(); - return service; - } - rcu_read_unlock(); - dev_dbg(instance->state->dev, "core: Invalid service handle 0x%x\n", handle); - return service; -} - -struct vchiq_service * -__next_service_by_instance(struct vchiq_state *state, - struct vchiq_instance *instance, - int *pidx) -{ - struct vchiq_service *service = NULL; - int idx = *pidx; - - while (idx < state->unused_service) { - struct vchiq_service *srv; - - srv = rcu_dereference(state->services[idx]); - idx++; - if (srv && srv->srvstate != VCHIQ_SRVSTATE_FREE && - srv->instance == instance) { - service = srv; - break; - } - } - - *pidx = idx; - return service; -} - -struct vchiq_service * -next_service_by_instance(struct vchiq_state *state, - struct vchiq_instance *instance, - int *pidx) -{ - struct vchiq_service *service; - - rcu_read_lock(); - while (1) { - service = __next_service_by_instance(state, instance, pidx); - if (!service) - break; - if (kref_get_unless_zero(&service->ref_count)) { - service = rcu_pointer_handoff(service); - break; - } - } - rcu_read_unlock(); - return service; -} - -void -vchiq_service_get(struct vchiq_service *service) -{ - if (!service) { - WARN(1, "%s service is NULL\n", __func__); - return; - } - kref_get(&service->ref_count); -} - -static void service_release(struct kref *kref) -{ - struct vchiq_service *service = - container_of(kref, struct vchiq_service, ref_count); - struct vchiq_state *state = service->state; - - WARN_ON(service->srvstate != VCHIQ_SRVSTATE_FREE); - rcu_assign_pointer(state->services[service->localport], NULL); - if (service->userdata_term) - service->userdata_term(service->base.userdata); - kfree_rcu(service, rcu); -} - -void -vchiq_service_put(struct vchiq_service *service) -{ - if (!service) { - WARN(1, "%s: service is NULL\n", __func__); - return; - } - kref_put(&service->ref_count, service_release); -} - -int -vchiq_get_client_id(struct vchiq_instance *instance, unsigned int handle) -{ - struct vchiq_service *service; - int id; - - rcu_read_lock(); - service = handle_to_service(instance, handle); - id = service ? service->client_id : 0; - rcu_read_unlock(); - return id; -} - -void * -vchiq_get_service_userdata(struct vchiq_instance *instance, unsigned int handle) -{ - void *userdata; - struct vchiq_service *service; - - rcu_read_lock(); - service = handle_to_service(instance, handle); - userdata = service ? service->base.userdata : NULL; - rcu_read_unlock(); - return userdata; -} -EXPORT_SYMBOL(vchiq_get_service_userdata); - -static void -mark_service_closing_internal(struct vchiq_service *service, int sh_thread) -{ - struct vchiq_state *state = service->state; - struct vchiq_service_quota *quota; - - service->closing = 1; - - /* Synchronise with other threads. */ - mutex_lock(&state->recycle_mutex); - mutex_unlock(&state->recycle_mutex); - if (!sh_thread || (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT)) { - /* - * If we're pausing then the slot_mutex is held until resume - * by the slot handler. Therefore don't try to acquire this - * mutex if we're the slot handler and in the pause sent state. - * We don't need to in this case anyway. - */ - mutex_lock(&state->slot_mutex); - mutex_unlock(&state->slot_mutex); - } - - /* Unblock any sending thread. */ - quota = &state->service_quotas[service->localport]; - complete("a->quota_event); -} - -static void -mark_service_closing(struct vchiq_service *service) -{ - mark_service_closing_internal(service, 0); -} - -static inline int -make_service_callback(struct vchiq_service *service, enum vchiq_reason reason, - struct vchiq_header *header, struct vchiq_bulk *bulk) -{ - void *cb_data = NULL; - void __user *cb_userdata = NULL; - int status; - - /* - * If a bulk transfer is in progress, pass bulk->cb_*data to the - * callback function. - */ - if (bulk) { - cb_data = bulk->cb_data; - cb_userdata = bulk->cb_userdata; - } - - dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %p, %p %p)\n", - service->state->id, service->localport, reason_names[reason], - header, cb_data, cb_userdata); - status = service->base.callback(service->instance, reason, header, service->handle, - cb_data, cb_userdata); - if (status && (status != -EAGAIN)) { - dev_warn(service->state->dev, - "core: %d: ignoring ERROR from callback to service %x\n", - service->state->id, service->handle); - status = 0; - } - - if (reason != VCHIQ_MESSAGE_AVAILABLE) - vchiq_release_message(service->instance, service->handle, header); - - return status; -} - -inline void -vchiq_set_conn_state(struct vchiq_state *state, enum vchiq_connstate newstate) -{ - enum vchiq_connstate oldstate = state->conn_state; - - dev_dbg(state->dev, "core: %d: %s->%s\n", - state->id, conn_state_names[oldstate], conn_state_names[newstate]); - state->conn_state = newstate; - vchiq_platform_conn_state_changed(state, oldstate, newstate); -} - -/* This initialises a single remote_event, and the associated wait_queue. */ -static inline void -remote_event_create(wait_queue_head_t *wq, struct remote_event *event) -{ - event->armed = 0; - /* - * Don't clear the 'fired' flag because it may already have been set - * by the other side. - */ - init_waitqueue_head(wq); -} - -/* - * All the event waiting routines in VCHIQ used a custom semaphore - * implementation that filtered most signals. This achieved a behaviour similar - * to the "killable" family of functions. While cleaning up this code all the - * routines where switched to the "interruptible" family of functions, as the - * former was deemed unjustified and the use "killable" set all VCHIQ's - * threads in D state. - * - * Returns: 0 on success, a negative error code on failure - */ -static inline int -remote_event_wait(wait_queue_head_t *wq, struct remote_event *event) -{ - int ret = 0; - - if (!event->fired) { - event->armed = 1; - dsb(sy); - ret = wait_event_interruptible(*wq, event->fired); - if (ret) { - event->armed = 0; - return ret; - } - event->armed = 0; - /* Ensure that the peer sees that we are not waiting (armed == 0). */ - wmb(); - } - - event->fired = 0; - return ret; -} - -static void -remote_event_signal(struct vchiq_state *state, struct remote_event *event) -{ - struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(state->dev); - - /* - * Ensure that all writes to shared data structures have completed - * before signalling the peer. - */ - wmb(); - - event->fired = 1; - - dsb(sy); /* data barrier operation */ - - if (event->armed) - writel(0, mgmt->regs + BELL2); /* trigger vc interrupt */ -} - -/* - * Acknowledge that the event has been signalled, and wake any waiters. Usually - * called as a result of the doorbell being rung. - */ -static inline void -remote_event_signal_local(wait_queue_head_t *wq, struct remote_event *event) -{ - event->fired = 1; - event->armed = 0; - wake_up_all(wq); -} - -/* Check if a single event has been signalled, waking the waiters if it has. */ -static inline void -remote_event_poll(wait_queue_head_t *wq, struct remote_event *event) -{ - if (event->fired && event->armed) - remote_event_signal_local(wq, event); -} - -/* - * VCHIQ used a small, fixed number of remote events. It is simplest to - * enumerate them here for polling. - */ -void -remote_event_pollall(struct vchiq_state *state) -{ - remote_event_poll(&state->sync_trigger_event, &state->local->sync_trigger); - remote_event_poll(&state->sync_release_event, &state->local->sync_release); - remote_event_poll(&state->trigger_event, &state->local->trigger); - remote_event_poll(&state->recycle_event, &state->local->recycle); -} - -/* - * Round up message sizes so that any space at the end of a slot is always big - * enough for a header. This relies on header size being a power of two, which - * has been verified earlier by a static assertion. - */ - -static inline size_t -calc_stride(size_t size) -{ - /* Allow room for the header */ - size += sizeof(struct vchiq_header); - - /* Round up */ - return (size + sizeof(struct vchiq_header) - 1) & - ~(sizeof(struct vchiq_header) - 1); -} - -/* Called by the slot handler thread */ -static struct vchiq_service * -get_listening_service(struct vchiq_state *state, int fourcc) -{ - int i; - - WARN_ON(fourcc == VCHIQ_FOURCC_INVALID); - - rcu_read_lock(); - for (i = 0; i < state->unused_service; i++) { - struct vchiq_service *service; - - service = rcu_dereference(state->services[i]); - if (service && - service->public_fourcc == fourcc && - (service->srvstate == VCHIQ_SRVSTATE_LISTENING || - (service->srvstate == VCHIQ_SRVSTATE_OPEN && - service->remoteport == VCHIQ_PORT_FREE)) && - kref_get_unless_zero(&service->ref_count)) { - service = rcu_pointer_handoff(service); - rcu_read_unlock(); - return service; - } - } - rcu_read_unlock(); - return NULL; -} - -/* Called by the slot handler thread */ -static struct vchiq_service * -get_connected_service(struct vchiq_state *state, unsigned int port) -{ - int i; - - rcu_read_lock(); - for (i = 0; i < state->unused_service; i++) { - struct vchiq_service *service = - rcu_dereference(state->services[i]); - - if (service && service->srvstate == VCHIQ_SRVSTATE_OPEN && - service->remoteport == port && - kref_get_unless_zero(&service->ref_count)) { - service = rcu_pointer_handoff(service); - rcu_read_unlock(); - return service; - } - } - rcu_read_unlock(); - return NULL; -} - -inline void -request_poll(struct vchiq_state *state, struct vchiq_service *service, - int poll_type) -{ - u32 value; - int index; - - if (!service) - goto skip_service; - - do { - value = atomic_read(&service->poll_flags); - } while (atomic_cmpxchg(&service->poll_flags, value, - value | BIT(poll_type)) != value); - - index = BITSET_WORD(service->localport); - do { - value = atomic_read(&state->poll_services[index]); - } while (atomic_cmpxchg(&state->poll_services[index], - value, value | BIT(service->localport & 0x1f)) != value); - -skip_service: - state->poll_needed = 1; - /* Ensure the slot handler thread sees the poll_needed flag. */ - wmb(); - - /* ... and ensure the slot handler runs. */ - remote_event_signal_local(&state->trigger_event, &state->local->trigger); -} - -/* - * Called from queue_message, by the slot handler and application threads, - * with slot_mutex held - */ -static struct vchiq_header * -reserve_space(struct vchiq_state *state, size_t space, int is_blocking) -{ - struct vchiq_shared_state *local = state->local; - int tx_pos = state->local_tx_pos; - int slot_space = VCHIQ_SLOT_SIZE - (tx_pos & VCHIQ_SLOT_MASK); - - if (space > slot_space) { - struct vchiq_header *header; - /* Fill the remaining space with padding */ - WARN_ON(!state->tx_data); - header = (struct vchiq_header *) - (state->tx_data + (tx_pos & VCHIQ_SLOT_MASK)); - header->msgid = VCHIQ_MSGID_PADDING; - header->size = slot_space - sizeof(struct vchiq_header); - - tx_pos += slot_space; - } - - /* If necessary, get the next slot. */ - if ((tx_pos & VCHIQ_SLOT_MASK) == 0) { - int slot_index; - - /* If there is no free slot... */ - - if (!try_wait_for_completion(&state->slot_available_event)) { - /* ...wait for one. */ - - VCHIQ_STATS_INC(state, slot_stalls); - - /* But first, flush through the last slot. */ - state->local_tx_pos = tx_pos; - local->tx_pos = tx_pos; - remote_event_signal(state, &state->remote->trigger); - - if (!is_blocking || - (wait_for_completion_interruptible(&state->slot_available_event))) - return NULL; /* No space available */ - } - - if (tx_pos == (state->slot_queue_available * VCHIQ_SLOT_SIZE)) { - complete(&state->slot_available_event); - dev_warn(state->dev, "%s: invalid tx_pos: %d\n", - __func__, tx_pos); - return NULL; - } - - slot_index = local->slot_queue[SLOT_QUEUE_INDEX_FROM_POS_MASKED(tx_pos)]; - state->tx_data = - (char *)SLOT_DATA_FROM_INDEX(state, slot_index); - } - - state->local_tx_pos = tx_pos + space; - - return (struct vchiq_header *)(state->tx_data + - (tx_pos & VCHIQ_SLOT_MASK)); -} - -static void -process_free_data_message(struct vchiq_state *state, u32 *service_found, - struct vchiq_header *header) -{ - int msgid = header->msgid; - int port = VCHIQ_MSG_SRCPORT(msgid); - struct vchiq_service_quota *quota = &state->service_quotas[port]; - int count; - - spin_lock(&state->quota_spinlock); - count = quota->message_use_count; - if (count > 0) - quota->message_use_count = count - 1; - spin_unlock(&state->quota_spinlock); - - if (count == quota->message_quota) { - /* - * Signal the service that it - * has dropped below its quota - */ - complete("a->quota_event); - } else if (count == 0) { - dev_err(state->dev, - "core: service %d message_use_count=%d (header %p, msgid %x, header->msgid %x, header->size %x)\n", - port, quota->message_use_count, header, msgid, - header->msgid, header->size); - WARN(1, "invalid message use count\n"); - } - if (!BITSET_IS_SET(service_found, port)) { - /* Set the found bit for this service */ - BITSET_SET(service_found, port); - - spin_lock(&state->quota_spinlock); - count = quota->slot_use_count; - if (count > 0) - quota->slot_use_count = count - 1; - spin_unlock(&state->quota_spinlock); - - if (count > 0) { - /* - * Signal the service in case - * it has dropped below its quota - */ - complete("a->quota_event); - dev_dbg(state->dev, "core: %d: pfq:%d %x@%p - slot_use->%d\n", - state->id, port, header->size, header, count - 1); - } else { - dev_err(state->dev, - "core: service %d slot_use_count=%d (header %p, msgid %x, header->msgid %x, header->size %x)\n", - port, count, header, msgid, header->msgid, header->size); - WARN(1, "bad slot use count\n"); - } - } -} - -/* Called by the recycle thread. */ -static void -process_free_queue(struct vchiq_state *state, u32 *service_found, - size_t length) -{ - struct vchiq_shared_state *local = state->local; - int slot_queue_available; - - /* - * Find slots which have been freed by the other side, and return them - * to the available queue. - */ - slot_queue_available = state->slot_queue_available; - - /* - * Use a memory barrier to ensure that any state that may have been - * modified by another thread is not masked by stale prefetched - * values. - */ - mb(); - - while (slot_queue_available != local->slot_queue_recycle) { - unsigned int pos; - int slot_index = local->slot_queue[slot_queue_available & - VCHIQ_SLOT_QUEUE_MASK]; - char *data = (char *)SLOT_DATA_FROM_INDEX(state, slot_index); - int data_found = 0; - - slot_queue_available++; - /* - * Beware of the address dependency - data is calculated - * using an index written by the other side. - */ - rmb(); - - dev_dbg(state->dev, "core: %d: pfq %d=%p %x %x\n", - state->id, slot_index, data, local->slot_queue_recycle, - slot_queue_available); - - /* Initialise the bitmask for services which have used this slot */ - memset(service_found, 0, length); - - pos = 0; - - while (pos < VCHIQ_SLOT_SIZE) { - struct vchiq_header *header = - (struct vchiq_header *)(data + pos); - int msgid = header->msgid; - - if (VCHIQ_MSG_TYPE(msgid) == VCHIQ_MSG_DATA) { - process_free_data_message(state, service_found, - header); - data_found = 1; - } - - pos += calc_stride(header->size); - if (pos > VCHIQ_SLOT_SIZE) { - dev_err(state->dev, - "core: pfq - pos %x: header %p, msgid %x, header->msgid %x, header->size %x\n", - pos, header, msgid, header->msgid, header->size); - WARN(1, "invalid slot position\n"); - } - } - - if (data_found) { - int count; - - spin_lock(&state->quota_spinlock); - count = state->data_use_count; - if (count > 0) - state->data_use_count = count - 1; - spin_unlock(&state->quota_spinlock); - if (count == state->data_quota) - complete(&state->data_quota_event); - } - - /* - * Don't allow the slot to be reused until we are no - * longer interested in it. - */ - mb(); - - state->slot_queue_available = slot_queue_available; - complete(&state->slot_available_event); - } -} - -static ssize_t -memcpy_copy_callback(void *context, void *dest, size_t offset, size_t maxsize) -{ - memcpy(dest + offset, context + offset, maxsize); - return maxsize; -} - -static ssize_t -copy_message_data(ssize_t (*copy_callback)(void *context, void *dest, size_t offset, - size_t maxsize), - void *context, - void *dest, - size_t size) -{ - size_t pos = 0; - - while (pos < size) { - ssize_t callback_result; - size_t max_bytes = size - pos; - - callback_result = copy_callback(context, dest + pos, pos, - max_bytes); - - if (callback_result < 0) - return callback_result; - - if (!callback_result) - return -EIO; - - if (callback_result > max_bytes) - return -EIO; - - pos += callback_result; - } - - return size; -} - -/* Called by the slot handler and application threads */ -static int -queue_message(struct vchiq_state *state, struct vchiq_service *service, - int msgid, - ssize_t (*copy_callback)(void *context, void *dest, - size_t offset, size_t maxsize), - void *context, size_t size, int flags) -{ - struct vchiq_shared_state *local; - struct vchiq_service_quota *quota = NULL; - struct vchiq_header *header; - int type = VCHIQ_MSG_TYPE(msgid); - int svc_fourcc; - - size_t stride; - - local = state->local; - - stride = calc_stride(size); - - WARN_ON(stride > VCHIQ_SLOT_SIZE); - - if (!(flags & QMFLAGS_NO_MUTEX_LOCK) && - mutex_lock_killable(&state->slot_mutex)) - return -EINTR; - - if (type == VCHIQ_MSG_DATA) { - int tx_end_index; - - if (!service) { - WARN(1, "%s: service is NULL\n", __func__); - mutex_unlock(&state->slot_mutex); - return -EINVAL; - } - - WARN_ON(flags & (QMFLAGS_NO_MUTEX_LOCK | - QMFLAGS_NO_MUTEX_UNLOCK)); - - if (service->closing) { - /* The service has been closed */ - mutex_unlock(&state->slot_mutex); - return -EHOSTDOWN; - } - - quota = &state->service_quotas[service->localport]; - - spin_lock(&state->quota_spinlock); - - /* - * Ensure this service doesn't use more than its quota of - * messages or slots - */ - tx_end_index = SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos + stride - 1); - - /* - * Ensure data messages don't use more than their quota of - * slots - */ - while ((tx_end_index != state->previous_data_index) && - (state->data_use_count == state->data_quota)) { - VCHIQ_STATS_INC(state, data_stalls); - spin_unlock(&state->quota_spinlock); - mutex_unlock(&state->slot_mutex); - - if (wait_for_completion_killable(&state->data_quota_event)) - return -EINTR; - - mutex_lock(&state->slot_mutex); - spin_lock(&state->quota_spinlock); - tx_end_index = SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos + stride - 1); - if ((tx_end_index == state->previous_data_index) || - (state->data_use_count < state->data_quota)) { - /* Pass the signal on to other waiters */ - complete(&state->data_quota_event); - break; - } - } - - while ((quota->message_use_count == quota->message_quota) || - ((tx_end_index != quota->previous_tx_index) && - (quota->slot_use_count == quota->slot_quota))) { - spin_unlock(&state->quota_spinlock); - dev_dbg(state->dev, - "core: %d: qm:%d %s,%zx - quota stall (msg %d, slot %d)\n", - state->id, service->localport, msg_type_str(type), size, - quota->message_use_count, quota->slot_use_count); - VCHIQ_SERVICE_STATS_INC(service, quota_stalls); - mutex_unlock(&state->slot_mutex); - if (wait_for_completion_killable("a->quota_event)) - return -EINTR; - if (service->closing) - return -EHOSTDOWN; - if (mutex_lock_killable(&state->slot_mutex)) - return -EINTR; - if (service->srvstate != VCHIQ_SRVSTATE_OPEN) { - /* The service has been closed */ - mutex_unlock(&state->slot_mutex); - return -EHOSTDOWN; - } - spin_lock(&state->quota_spinlock); - tx_end_index = SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos + stride - 1); - } - - spin_unlock(&state->quota_spinlock); - } - - header = reserve_space(state, stride, flags & QMFLAGS_IS_BLOCKING); - - if (!header) { - if (service) - VCHIQ_SERVICE_STATS_INC(service, slot_stalls); - /* - * In the event of a failure, return the mutex to the - * state it was in - */ - if (!(flags & QMFLAGS_NO_MUTEX_LOCK)) - mutex_unlock(&state->slot_mutex); - return -EAGAIN; - } - - if (type == VCHIQ_MSG_DATA) { - ssize_t callback_result; - int tx_end_index; - int slot_use_count; - - dev_dbg(state->dev, "core: %d: qm %s@%p,%zx (%d->%d)\n", - state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size, - VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid)); - - WARN_ON(flags & (QMFLAGS_NO_MUTEX_LOCK | - QMFLAGS_NO_MUTEX_UNLOCK)); - - callback_result = - copy_message_data(copy_callback, context, - header->data, size); - - if (callback_result < 0) { - mutex_unlock(&state->slot_mutex); - VCHIQ_SERVICE_STATS_INC(service, error_count); - return -EINVAL; - } - - vchiq_log_dump_mem(state->dev, "Sent", 0, - header->data, - min_t(size_t, 16, callback_result)); - - spin_lock(&state->quota_spinlock); - quota->message_use_count++; - - tx_end_index = - SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos - 1); - - /* - * If this transmission can't fit in the last slot used by any - * service, the data_use_count must be increased. - */ - if (tx_end_index != state->previous_data_index) { - state->previous_data_index = tx_end_index; - state->data_use_count++; - } - - /* - * If this isn't the same slot last used by this service, - * the service's slot_use_count must be increased. - */ - if (tx_end_index != quota->previous_tx_index) { - quota->previous_tx_index = tx_end_index; - slot_use_count = ++quota->slot_use_count; - } else { - slot_use_count = 0; - } - - spin_unlock(&state->quota_spinlock); - - if (slot_use_count) - dev_dbg(state->dev, "core: %d: qm:%d %s,%zx - slot_use->%d (hdr %p)\n", - state->id, service->localport, msg_type_str(VCHIQ_MSG_TYPE(msgid)), - size, slot_use_count, header); - - VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); - VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); - } else { - dev_dbg(state->dev, "core: %d: qm %s@%p,%zx (%d->%d)\n", - state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size, - VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid)); - if (size != 0) { - /* - * It is assumed for now that this code path - * only happens from calls inside this file. - * - * External callers are through the vchiq_queue_message - * path which always sets the type to be VCHIQ_MSG_DATA - * - * At first glance this appears to be correct but - * more review is needed. - */ - copy_message_data(copy_callback, context, - header->data, size); - } - VCHIQ_STATS_INC(state, ctrl_tx_count); - } - - header->msgid = msgid; - header->size = size; - - svc_fourcc = service ? service->base.fourcc - : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); - - dev_dbg(state->dev, "core_msg: Sent Msg %s(%u) to %p4cc s:%u d:%d len:%zu\n", - msg_type_str(VCHIQ_MSG_TYPE(msgid)), - VCHIQ_MSG_TYPE(msgid), &svc_fourcc, - VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid), size); - - /* Make sure the new header is visible to the peer. */ - wmb(); - - /* Make the new tx_pos visible to the peer. */ - local->tx_pos = state->local_tx_pos; - wmb(); - - if (service && (type == VCHIQ_MSG_CLOSE)) - set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT); - - if (!(flags & QMFLAGS_NO_MUTEX_UNLOCK)) - mutex_unlock(&state->slot_mutex); - - remote_event_signal(state, &state->remote->trigger); - - return 0; -} - -/* Called by the slot handler and application threads */ -static int -queue_message_sync(struct vchiq_state *state, struct vchiq_service *service, - int msgid, - ssize_t (*copy_callback)(void *context, void *dest, - size_t offset, size_t maxsize), - void *context, int size) -{ - struct vchiq_shared_state *local; - struct vchiq_header *header; - ssize_t callback_result; - int svc_fourcc; - int ret; - - local = state->local; - - if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_RESUME && - mutex_lock_killable(&state->sync_mutex)) - return -EAGAIN; - - ret = remote_event_wait(&state->sync_release_event, &local->sync_release); - if (ret) - return ret; - - /* Ensure that reads don't overtake the remote_event_wait. */ - rmb(); - - header = (struct vchiq_header *)SLOT_DATA_FROM_INDEX(state, - local->slot_sync); - - { - int oldmsgid = header->msgid; - - if (oldmsgid != VCHIQ_MSGID_PADDING) - dev_err(state->dev, "core: %d: qms - msgid %x, not PADDING\n", - state->id, oldmsgid); - } - - dev_dbg(state->dev, "sync: %d: qms %s@%p,%x (%d->%d)\n", - state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size, - VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid)); - - callback_result = copy_message_data(copy_callback, context, - header->data, size); - - if (callback_result < 0) { - mutex_unlock(&state->slot_mutex); - VCHIQ_SERVICE_STATS_INC(service, error_count); - return -EINVAL; - } - - if (service) { - vchiq_log_dump_mem(state->dev, "Sent", 0, - header->data, - min_t(size_t, 16, callback_result)); - - VCHIQ_SERVICE_STATS_INC(service, ctrl_tx_count); - VCHIQ_SERVICE_STATS_ADD(service, ctrl_tx_bytes, size); - } else { - VCHIQ_STATS_INC(state, ctrl_tx_count); - } - - header->size = size; - header->msgid = msgid; - - svc_fourcc = service ? service->base.fourcc - : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); - - dev_dbg(state->dev, - "sync: Sent Sync Msg %s(%u) to %p4cc s:%u d:%d len:%d\n", - msg_type_str(VCHIQ_MSG_TYPE(msgid)), VCHIQ_MSG_TYPE(msgid), - &svc_fourcc, VCHIQ_MSG_SRCPORT(msgid), - VCHIQ_MSG_DSTPORT(msgid), size); - - remote_event_signal(state, &state->remote->sync_trigger); - - if (VCHIQ_MSG_TYPE(msgid) != VCHIQ_MSG_PAUSE) - mutex_unlock(&state->sync_mutex); - - return 0; -} - -static inline void -claim_slot(struct vchiq_slot_info *slot) -{ - slot->use_count++; -} - -static void -release_slot(struct vchiq_state *state, struct vchiq_slot_info *slot_info, - struct vchiq_header *header, struct vchiq_service *service) -{ - mutex_lock(&state->recycle_mutex); - - if (header) { - int msgid = header->msgid; - - if (((msgid & VCHIQ_MSGID_CLAIMED) == 0) || (service && service->closing)) { - mutex_unlock(&state->recycle_mutex); - return; - } - - /* Rewrite the message header to prevent a double release */ - header->msgid = msgid & ~VCHIQ_MSGID_CLAIMED; - } - - slot_info->release_count++; - - if (slot_info->release_count == slot_info->use_count) { - int slot_queue_recycle; - /* Add to the freed queue */ - - /* - * A read barrier is necessary here to prevent speculative - * fetches of remote->slot_queue_recycle from overtaking the - * mutex. - */ - rmb(); - - slot_queue_recycle = state->remote->slot_queue_recycle; - state->remote->slot_queue[slot_queue_recycle & - VCHIQ_SLOT_QUEUE_MASK] = - SLOT_INDEX_FROM_INFO(state, slot_info); - state->remote->slot_queue_recycle = slot_queue_recycle + 1; - dev_dbg(state->dev, "core: %d: %d - recycle->%x\n", - state->id, SLOT_INDEX_FROM_INFO(state, slot_info), - state->remote->slot_queue_recycle); - - /* - * A write barrier is necessary, but remote_event_signal - * contains one. - */ - remote_event_signal(state, &state->remote->recycle); - } - - mutex_unlock(&state->recycle_mutex); -} - -static inline enum vchiq_reason -get_bulk_reason(struct vchiq_bulk *bulk) -{ - if (bulk->dir == VCHIQ_BULK_TRANSMIT) { - if (bulk->actual == VCHIQ_BULK_ACTUAL_ABORTED) - return VCHIQ_BULK_TRANSMIT_ABORTED; - - return VCHIQ_BULK_TRANSMIT_DONE; - } - - if (bulk->actual == VCHIQ_BULK_ACTUAL_ABORTED) - return VCHIQ_BULK_RECEIVE_ABORTED; - - return VCHIQ_BULK_RECEIVE_DONE; -} - -static int service_notify_bulk(struct vchiq_service *service, - struct vchiq_bulk *bulk) -{ - if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) { - if (bulk->dir == VCHIQ_BULK_TRANSMIT) { - VCHIQ_SERVICE_STATS_INC(service, bulk_tx_count); - VCHIQ_SERVICE_STATS_ADD(service, bulk_tx_bytes, - bulk->actual); - } else { - VCHIQ_SERVICE_STATS_INC(service, bulk_rx_count); - VCHIQ_SERVICE_STATS_ADD(service, bulk_rx_bytes, - bulk->actual); - } - } else { - VCHIQ_SERVICE_STATS_INC(service, bulk_aborted_count); - } - - if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) { - struct bulk_waiter *waiter; - - spin_lock(&service->state->bulk_waiter_spinlock); - waiter = bulk->waiter; - if (waiter) { - waiter->actual = bulk->actual; - complete(&waiter->event); - } - spin_unlock(&service->state->bulk_waiter_spinlock); - } else if (bulk->mode == VCHIQ_BULK_MODE_CALLBACK) { - enum vchiq_reason reason = get_bulk_reason(bulk); - - return make_service_callback(service, reason, NULL, bulk); - } - - return 0; -} - -/* Called by the slot handler - don't hold the bulk mutex */ -static int -notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue, - int retry_poll) -{ - int status = 0; - - dev_dbg(service->state->dev, - "core: %d: nb:%d %cx - p=%x rn=%x r=%x\n", - service->state->id, service->localport, - (queue == &service->bulk_tx) ? 't' : 'r', - queue->process, queue->remote_notify, queue->remove); - - queue->remote_notify = queue->process; - - while (queue->remove != queue->remote_notify) { - struct vchiq_bulk *bulk = - &queue->bulks[BULK_INDEX(queue->remove)]; - - /* - * Only generate callbacks for non-dummy bulk - * requests, and non-terminated services - */ - if (bulk->dma_addr && service->instance) { - status = service_notify_bulk(service, bulk); - if (status == -EAGAIN) - break; - } - - queue->remove++; - complete(&service->bulk_remove_event); - } - if (!retry_poll) - status = 0; - - if (status == -EAGAIN) - request_poll(service->state, service, (queue == &service->bulk_tx) ? - VCHIQ_POLL_TXNOTIFY : VCHIQ_POLL_RXNOTIFY); - - return status; -} - -static void -poll_services_of_group(struct vchiq_state *state, int group) -{ - u32 flags = atomic_xchg(&state->poll_services[group], 0); - int i; - - for (i = 0; flags; i++) { - struct vchiq_service *service; - u32 service_flags; - - if ((flags & BIT(i)) == 0) - continue; - - service = find_service_by_port(state, (group << 5) + i); - flags &= ~BIT(i); - - if (!service) - continue; - - service_flags = atomic_xchg(&service->poll_flags, 0); - if (service_flags & BIT(VCHIQ_POLL_REMOVE)) { - dev_dbg(state->dev, "core: %d: ps - remove %d<->%d\n", - state->id, service->localport, service->remoteport); - - /* - * Make it look like a client, because - * it must be removed and not left in - * the LISTENING state. - */ - service->public_fourcc = VCHIQ_FOURCC_INVALID; - - if (vchiq_close_service_internal(service, NO_CLOSE_RECVD)) - request_poll(state, service, VCHIQ_POLL_REMOVE); - } else if (service_flags & BIT(VCHIQ_POLL_TERMINATE)) { - dev_dbg(state->dev, "core: %d: ps - terminate %d<->%d\n", - state->id, service->localport, service->remoteport); - if (vchiq_close_service_internal(service, NO_CLOSE_RECVD)) - request_poll(state, service, VCHIQ_POLL_TERMINATE); - } - if (service_flags & BIT(VCHIQ_POLL_TXNOTIFY)) - notify_bulks(service, &service->bulk_tx, RETRY_POLL); - if (service_flags & BIT(VCHIQ_POLL_RXNOTIFY)) - notify_bulks(service, &service->bulk_rx, RETRY_POLL); - vchiq_service_put(service); - } -} - -/* Called by the slot handler thread */ -static void -poll_services(struct vchiq_state *state) -{ - int group; - - for (group = 0; group < BITSET_SIZE(state->unused_service); group++) - poll_services_of_group(state, group); -} - -static void -cleanup_pagelistinfo(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo) -{ - if (pagelistinfo->scatterlist_mapped) { - dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist, - pagelistinfo->num_pages, pagelistinfo->dma_dir); - } - - if (pagelistinfo->pages_need_release) - unpin_user_pages(pagelistinfo->pages, pagelistinfo->num_pages); - - dma_free_coherent(instance->state->dev, pagelistinfo->pagelist_buffer_size, - pagelistinfo->pagelist, pagelistinfo->dma_addr); -} - -static inline bool -is_adjacent_block(u32 *addrs, dma_addr_t addr, unsigned int k) -{ - u32 tmp; - - if (!k) - return false; - - tmp = (addrs[k - 1] & PAGE_MASK) + - (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT); - - return tmp == (addr & PAGE_MASK); -} - -/* There is a potential problem with partial cache lines (pages?) - * at the ends of the block when reading. If the CPU accessed anything in - * the same line (page?) then it may have pulled old data into the cache, - * obscuring the new data underneath. We can solve this by transferring the - * partial cache lines separately, and allowing the ARM to copy into the - * cached area. - */ -static struct vchiq_pagelist_info * -create_pagelist(struct vchiq_instance *instance, struct vchiq_bulk *bulk) -{ - struct vchiq_drv_mgmt *drv_mgmt; - struct pagelist *pagelist; - struct vchiq_pagelist_info *pagelistinfo; - struct page **pages; - u32 *addrs; - unsigned int num_pages, offset, i, k; - int actual_pages; - size_t pagelist_size; - struct scatterlist *scatterlist, *sg; - int dma_buffers; - unsigned int cache_line_size; - dma_addr_t dma_addr; - size_t count = bulk->size; - unsigned short type = (bulk->dir == VCHIQ_BULK_RECEIVE) - ? PAGELIST_READ : PAGELIST_WRITE; - - if (count >= INT_MAX - PAGE_SIZE) - return NULL; - - drv_mgmt = dev_get_drvdata(instance->state->dev); - - if (bulk->offset) - offset = (uintptr_t)bulk->offset & (PAGE_SIZE - 1); - else - offset = (uintptr_t)bulk->uoffset & (PAGE_SIZE - 1); - num_pages = DIV_ROUND_UP(count + offset, PAGE_SIZE); - - if ((size_t)num_pages > (SIZE_MAX - sizeof(struct pagelist) - - sizeof(struct vchiq_pagelist_info)) / - (sizeof(u32) + sizeof(pages[0]) + - sizeof(struct scatterlist))) - return NULL; - - pagelist_size = sizeof(struct pagelist) + - (num_pages * sizeof(u32)) + - (num_pages * sizeof(pages[0]) + - (num_pages * sizeof(struct scatterlist))) + - sizeof(struct vchiq_pagelist_info); - - /* Allocate enough storage to hold the page pointers and the page - * list - */ - pagelist = dma_alloc_coherent(instance->state->dev, pagelist_size, &dma_addr, - GFP_KERNEL); - - dev_dbg(instance->state->dev, "arm: %p\n", pagelist); - - if (!pagelist) - return NULL; - - addrs = pagelist->addrs; - pages = (struct page **)(addrs + num_pages); - scatterlist = (struct scatterlist *)(pages + num_pages); - pagelistinfo = (struct vchiq_pagelist_info *) - (scatterlist + num_pages); - - pagelist->length = count; - pagelist->type = type; - pagelist->offset = offset; - - /* Populate the fields of the pagelistinfo structure */ - pagelistinfo->pagelist = pagelist; - pagelistinfo->pagelist_buffer_size = pagelist_size; - pagelistinfo->dma_addr = dma_addr; - pagelistinfo->dma_dir = (type == PAGELIST_WRITE) ? - DMA_TO_DEVICE : DMA_FROM_DEVICE; - pagelistinfo->num_pages = num_pages; - pagelistinfo->pages_need_release = 0; - pagelistinfo->pages = pages; - pagelistinfo->scatterlist = scatterlist; - pagelistinfo->scatterlist_mapped = 0; - - if (bulk->offset) { - unsigned long length = count; - unsigned int off = offset; - - for (actual_pages = 0; actual_pages < num_pages; - actual_pages++) { - struct page *pg = - vmalloc_to_page(((unsigned int *)bulk->offset + - (actual_pages * PAGE_SIZE))); - size_t bytes = PAGE_SIZE - off; - - if (!pg) { - cleanup_pagelistinfo(instance, pagelistinfo); - return NULL; - } - - if (bytes > length) - bytes = length; - pages[actual_pages] = pg; - length -= bytes; - off = 0; - } - /* do not try and release vmalloc pages */ - } else { - actual_pages = - pin_user_pages_fast((unsigned long)bulk->uoffset & PAGE_MASK, num_pages, - type == PAGELIST_READ, pages); - - if (actual_pages != num_pages) { - dev_dbg(instance->state->dev, "arm: Only %d/%d pages locked\n", - actual_pages, num_pages); - - /* This is probably due to the process being killed */ - if (actual_pages > 0) - unpin_user_pages(pages, actual_pages); - cleanup_pagelistinfo(instance, pagelistinfo); - return NULL; - } - /* release user pages */ - pagelistinfo->pages_need_release = 1; - } - - /* - * Initialize the scatterlist so that the magic cookie - * is filled if debugging is enabled - */ - sg_init_table(scatterlist, num_pages); - /* Now set the pages for each scatterlist */ - for (i = 0; i < num_pages; i++) { - unsigned int len = PAGE_SIZE - offset; - - if (len > count) - len = count; - sg_set_page(scatterlist + i, pages[i], len, offset); - offset = 0; - count -= len; - } - - dma_buffers = dma_map_sg(instance->state->dev, - scatterlist, - num_pages, - pagelistinfo->dma_dir); - - if (dma_buffers == 0) { - cleanup_pagelistinfo(instance, pagelistinfo); - return NULL; - } - - pagelistinfo->scatterlist_mapped = 1; - - /* Combine adjacent blocks for performance */ - k = 0; - for_each_sg(scatterlist, sg, dma_buffers, i) { - unsigned int len = sg_dma_len(sg); - dma_addr_t addr = sg_dma_address(sg); - - /* Note: addrs is the address + page_count - 1 - * The firmware expects blocks after the first to be page- - * aligned and a multiple of the page size - */ - WARN_ON(len == 0); - WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK)); - WARN_ON(i && (addr & ~PAGE_MASK)); - if (is_adjacent_block(addrs, addr, k)) - addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT); - else - addrs[k++] = (addr & PAGE_MASK) | - (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1); - } - - /* Partial cache lines (fragments) require special measures */ - cache_line_size = drv_mgmt->info->cache_line_size; - if ((type == PAGELIST_READ) && - ((pagelist->offset & (cache_line_size - 1)) || - ((pagelist->offset + pagelist->length) & (cache_line_size - 1)))) { - char *fragments; - - if (down_interruptible(&drv_mgmt->free_fragments_sema)) { - cleanup_pagelistinfo(instance, pagelistinfo); - return NULL; - } - - WARN_ON(!drv_mgmt->free_fragments); - - down(&drv_mgmt->free_fragments_mutex); - fragments = drv_mgmt->free_fragments; - WARN_ON(!fragments); - drv_mgmt->free_fragments = *(char **)drv_mgmt->free_fragments; - up(&drv_mgmt->free_fragments_mutex); - pagelist->type = PAGELIST_READ_WITH_FRAGMENTS + - (fragments - drv_mgmt->fragments_base) / drv_mgmt->fragments_size; - } - - return pagelistinfo; -} - -static void -free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo, - int actual) -{ - struct vchiq_drv_mgmt *drv_mgmt; - struct pagelist *pagelist = pagelistinfo->pagelist; - struct page **pages = pagelistinfo->pages; - unsigned int num_pages = pagelistinfo->num_pages; - unsigned int cache_line_size; - - dev_dbg(instance->state->dev, "arm: %p, %d\n", pagelistinfo->pagelist, actual); - - drv_mgmt = dev_get_drvdata(instance->state->dev); - - /* - * NOTE: dma_unmap_sg must be called before the - * cpu can touch any of the data/pages. - */ - dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist, - pagelistinfo->num_pages, pagelistinfo->dma_dir); - pagelistinfo->scatterlist_mapped = 0; - - /* Deal with any partial cache lines (fragments) */ - cache_line_size = drv_mgmt->info->cache_line_size; - if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS && drv_mgmt->fragments_base) { - char *fragments = drv_mgmt->fragments_base + - (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) * - drv_mgmt->fragments_size; - int head_bytes, tail_bytes; - - head_bytes = (cache_line_size - pagelist->offset) & - (cache_line_size - 1); - tail_bytes = (pagelist->offset + actual) & - (cache_line_size - 1); - - if ((actual >= 0) && (head_bytes != 0)) { - if (head_bytes > actual) - head_bytes = actual; - - memcpy_to_page(pages[0], pagelist->offset, - fragments, head_bytes); - } - if ((actual >= 0) && (head_bytes < actual) && - (tail_bytes != 0)) - memcpy_to_page(pages[num_pages - 1], - (pagelist->offset + actual) & - (PAGE_SIZE - 1) & ~(cache_line_size - 1), - fragments + cache_line_size, - tail_bytes); - - down(&drv_mgmt->free_fragments_mutex); - *(char **)fragments = drv_mgmt->free_fragments; - drv_mgmt->free_fragments = fragments; - up(&drv_mgmt->free_fragments_mutex); - up(&drv_mgmt->free_fragments_sema); - } - - /* Need to mark all the pages dirty. */ - if (pagelist->type != PAGELIST_WRITE && - pagelistinfo->pages_need_release) { - unsigned int i; - - for (i = 0; i < num_pages; i++) - set_page_dirty(pages[i]); - } - - cleanup_pagelistinfo(instance, pagelistinfo); -} - -static int -vchiq_prepare_bulk_data(struct vchiq_instance *instance, struct vchiq_bulk *bulk) -{ - struct vchiq_pagelist_info *pagelistinfo; - - pagelistinfo = create_pagelist(instance, bulk); - - if (!pagelistinfo) - return -ENOMEM; - - bulk->dma_addr = pagelistinfo->dma_addr; - - /* - * Store the pagelistinfo address in remote_data, - * which isn't used by the slave. - */ - bulk->remote_data = pagelistinfo; - - return 0; -} - -static void -vchiq_complete_bulk(struct vchiq_instance *instance, struct vchiq_bulk *bulk) -{ - if (bulk && bulk->remote_data && bulk->actual) - free_pagelist(instance, (struct vchiq_pagelist_info *)bulk->remote_data, - bulk->actual); -} - -/* Called with the bulk_mutex held */ -static void -abort_outstanding_bulks(struct vchiq_service *service, - struct vchiq_bulk_queue *queue) -{ - int is_tx = (queue == &service->bulk_tx); - - dev_dbg(service->state->dev, - "core: %d: aob:%d %cx - li=%x ri=%x p=%x\n", - service->state->id, service->localport, - is_tx ? 't' : 'r', queue->local_insert, - queue->remote_insert, queue->process); - - WARN_ON((int)(queue->local_insert - queue->process) < 0); - WARN_ON((int)(queue->remote_insert - queue->process) < 0); - - while ((queue->process != queue->local_insert) || - (queue->process != queue->remote_insert)) { - struct vchiq_bulk *bulk = &queue->bulks[BULK_INDEX(queue->process)]; - - if (queue->process == queue->remote_insert) { - /* fabricate a matching dummy bulk */ - bulk->remote_data = NULL; - bulk->remote_size = 0; - queue->remote_insert++; - } - - if (queue->process != queue->local_insert) { - vchiq_complete_bulk(service->instance, bulk); - - dev_dbg(service->state->dev, - "core_msg: %s %p4cc d:%d ABORTED - tx len:%d, rx len:%d\n", - is_tx ? "Send Bulk to" : "Recv Bulk from", - &service->base.fourcc, - service->remoteport, bulk->size, bulk->remote_size); - } else { - /* fabricate a matching dummy bulk */ - bulk->dma_addr = 0; - bulk->size = 0; - bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; - bulk->dir = is_tx ? VCHIQ_BULK_TRANSMIT : - VCHIQ_BULK_RECEIVE; - queue->local_insert++; - } - - queue->process++; - } -} - -static int -parse_open(struct vchiq_state *state, struct vchiq_header *header) -{ - const struct vchiq_open_payload *payload; - struct vchiq_openack_payload ack_payload; - struct vchiq_service *service = NULL; - int msgid, size; - int openack_id; - unsigned int localport, remoteport, fourcc; - short version, version_min; - - msgid = header->msgid; - size = header->size; - localport = VCHIQ_MSG_DSTPORT(msgid); - remoteport = VCHIQ_MSG_SRCPORT(msgid); - if (size < sizeof(struct vchiq_open_payload)) - goto fail_open; - - payload = (struct vchiq_open_payload *)header->data; - fourcc = payload->fourcc; - dev_dbg(state->dev, "core: %d: prs OPEN@%p (%d->'%p4cc')\n", - state->id, header, localport, &fourcc); - - service = get_listening_service(state, fourcc); - if (!service) - goto fail_open; - - /* A matching service exists */ - version = payload->version; - version_min = payload->version_min; - - if ((service->version < version_min) || (version < service->version_min)) { - /* Version mismatch */ - dev_err(state->dev, "%d: service %d (%p4cc) version mismatch - local (%d, min %d) vs. remote (%d, min %d)", - state->id, service->localport, &fourcc, - service->version, service->version_min, version, version_min); - vchiq_service_put(service); - service = NULL; - goto fail_open; - } - service->peer_version = version; - - if (service->srvstate != VCHIQ_SRVSTATE_LISTENING) - goto done; - - ack_payload.version = service->version; - openack_id = MAKE_OPENACK(service->localport, remoteport); - - if (state->version_common < VCHIQ_VERSION_SYNCHRONOUS_MODE) - service->sync = 0; - - /* Acknowledge the OPEN */ - if (service->sync) { - if (queue_message_sync(state, NULL, openack_id, - memcpy_copy_callback, - &ack_payload, - sizeof(ack_payload)) == -EAGAIN) - goto bail_not_ready; - - /* The service is now open */ - set_service_state(service, VCHIQ_SRVSTATE_OPENSYNC); - } else { - if (queue_message(state, NULL, openack_id, - memcpy_copy_callback, &ack_payload, - sizeof(ack_payload), 0) == -EINTR) - goto bail_not_ready; - - /* The service is now open */ - set_service_state(service, VCHIQ_SRVSTATE_OPEN); - } - -done: - /* Success - the message has been dealt with */ - vchiq_service_put(service); - return 1; - -fail_open: - /* No available service, or an invalid request - send a CLOSE */ - if (queue_message(state, NULL, MAKE_CLOSE(0, VCHIQ_MSG_SRCPORT(msgid)), - NULL, NULL, 0, 0) == -EINTR) - goto bail_not_ready; - - return 1; - -bail_not_ready: - if (service) - vchiq_service_put(service); - - return 0; -} - -/** - * parse_message() - parses a single message from the rx slot - * @state: vchiq state struct - * @header: message header - * - * Context: Process context - * - * Return: - * * >= 0 - size of the parsed message payload (without header) - * * -EINVAL - fatal error occurred, bail out is required - */ -static int -parse_message(struct vchiq_state *state, struct vchiq_header *header) -{ - struct vchiq_service *service = NULL; - unsigned int localport, remoteport; - int msgid, size, type, ret = -EINVAL; - int svc_fourcc; - - DEBUG_INITIALISE(state->local); - - DEBUG_VALUE(PARSE_HEADER, (int)(long)header); - msgid = header->msgid; - DEBUG_VALUE(PARSE_MSGID, msgid); - size = header->size; - type = VCHIQ_MSG_TYPE(msgid); - localport = VCHIQ_MSG_DSTPORT(msgid); - remoteport = VCHIQ_MSG_SRCPORT(msgid); - - if (type != VCHIQ_MSG_DATA) - VCHIQ_STATS_INC(state, ctrl_rx_count); - - switch (type) { - case VCHIQ_MSG_OPENACK: - case VCHIQ_MSG_CLOSE: - case VCHIQ_MSG_DATA: - case VCHIQ_MSG_BULK_RX: - case VCHIQ_MSG_BULK_TX: - case VCHIQ_MSG_BULK_RX_DONE: - case VCHIQ_MSG_BULK_TX_DONE: - service = find_service_by_port(state, localport); - if ((!service || - ((service->remoteport != remoteport) && - (service->remoteport != VCHIQ_PORT_FREE))) && - (localport == 0) && - (type == VCHIQ_MSG_CLOSE)) { - /* - * This could be a CLOSE from a client which - * hadn't yet received the OPENACK - look for - * the connected service - */ - if (service) - vchiq_service_put(service); - service = get_connected_service(state, remoteport); - if (service) - dev_warn(state->dev, - "core: %d: prs %s@%p (%d->%d) - found connected service %d\n", - state->id, msg_type_str(type), header, - remoteport, localport, service->localport); - } - - if (!service) { - dev_err(state->dev, - "core: %d: prs %s@%p (%d->%d) - invalid/closed service %d\n", - state->id, msg_type_str(type), header, remoteport, - localport, localport); - goto skip_message; - } - break; - default: - break; - } - - svc_fourcc = service ? service->base.fourcc - : VCHIQ_MAKE_FOURCC('?', '?', '?', '?'); - - dev_dbg(state->dev, "core_msg: Rcvd Msg %s(%u) from %p4cc s:%d d:%d len:%d\n", - msg_type_str(type), type, &svc_fourcc, remoteport, localport, size); - if (size > 0) - vchiq_log_dump_mem(state->dev, "Rcvd", 0, header->data, min(16, size)); - - if (((unsigned long)header & VCHIQ_SLOT_MASK) + - calc_stride(size) > VCHIQ_SLOT_SIZE) { - dev_err(state->dev, "core: header %p (msgid %x) - size %x too big for slot\n", - header, (unsigned int)msgid, (unsigned int)size); - WARN(1, "oversized for slot\n"); - } - - switch (type) { - case VCHIQ_MSG_OPEN: - WARN_ON(VCHIQ_MSG_DSTPORT(msgid)); - if (!parse_open(state, header)) - goto bail_not_ready; - break; - case VCHIQ_MSG_OPENACK: - if (size >= sizeof(struct vchiq_openack_payload)) { - const struct vchiq_openack_payload *payload = - (struct vchiq_openack_payload *) - header->data; - service->peer_version = payload->version; - } - dev_dbg(state->dev, - "core: %d: prs OPENACK@%p,%x (%d->%d) v:%d\n", - state->id, header, size, remoteport, localport, - service->peer_version); - if (service->srvstate == VCHIQ_SRVSTATE_OPENING) { - service->remoteport = remoteport; - set_service_state(service, VCHIQ_SRVSTATE_OPEN); - complete(&service->remove_event); - } else { - dev_err(state->dev, "core: OPENACK received in state %s\n", - srvstate_names[service->srvstate]); - } - break; - case VCHIQ_MSG_CLOSE: - WARN_ON(size); /* There should be no data */ - - dev_dbg(state->dev, "core: %d: prs CLOSE@%p (%d->%d)\n", - state->id, header, remoteport, localport); - - mark_service_closing_internal(service, 1); - - if (vchiq_close_service_internal(service, CLOSE_RECVD) == -EAGAIN) - goto bail_not_ready; - - dev_dbg(state->dev, "core: Close Service %p4cc s:%u d:%d\n", - &service->base.fourcc, service->localport, service->remoteport); - break; - case VCHIQ_MSG_DATA: - dev_dbg(state->dev, "core: %d: prs DATA@%p,%x (%d->%d)\n", - state->id, header, size, remoteport, localport); - - if ((service->remoteport == remoteport) && - (service->srvstate == VCHIQ_SRVSTATE_OPEN)) { - header->msgid = msgid | VCHIQ_MSGID_CLAIMED; - claim_slot(state->rx_info); - DEBUG_TRACE(PARSE_LINE); - if (make_service_callback(service, VCHIQ_MESSAGE_AVAILABLE, header, - NULL) == -EAGAIN) { - DEBUG_TRACE(PARSE_LINE); - goto bail_not_ready; - } - VCHIQ_SERVICE_STATS_INC(service, ctrl_rx_count); - VCHIQ_SERVICE_STATS_ADD(service, ctrl_rx_bytes, size); - } else { - VCHIQ_STATS_INC(state, error_count); - } - break; - case VCHIQ_MSG_CONNECT: - dev_dbg(state->dev, "core: %d: prs CONNECT@%p\n", - state->id, header); - state->version_common = ((struct vchiq_slot_zero *) - state->slot_data)->version; - complete(&state->connect); - break; - case VCHIQ_MSG_BULK_RX: - case VCHIQ_MSG_BULK_TX: - /* - * We should never receive a bulk request from the - * other side since we're not setup to perform as the - * master. - */ - WARN_ON(1); - break; - case VCHIQ_MSG_BULK_RX_DONE: - case VCHIQ_MSG_BULK_TX_DONE: - if ((service->remoteport == remoteport) && - (service->srvstate != VCHIQ_SRVSTATE_FREE)) { - struct vchiq_bulk_queue *queue; - struct vchiq_bulk *bulk; - - queue = (type == VCHIQ_MSG_BULK_RX_DONE) ? - &service->bulk_rx : &service->bulk_tx; - - DEBUG_TRACE(PARSE_LINE); - if (mutex_lock_killable(&service->bulk_mutex)) { - DEBUG_TRACE(PARSE_LINE); - goto bail_not_ready; - } - if ((int)(queue->remote_insert - - queue->local_insert) >= 0) { - dev_err(state->dev, - "core: %d: prs %s@%p (%d->%d) unexpected (ri=%d,li=%d)\n", - state->id, msg_type_str(type), header, remoteport, - localport, queue->remote_insert, queue->local_insert); - mutex_unlock(&service->bulk_mutex); - break; - } - if (queue->process != queue->remote_insert) { - dev_err(state->dev, "%s: p %x != ri %x\n", - __func__, queue->process, - queue->remote_insert); - mutex_unlock(&service->bulk_mutex); - goto bail_not_ready; - } - - bulk = &queue->bulks[BULK_INDEX(queue->remote_insert)]; - bulk->actual = *(int *)header->data; - queue->remote_insert++; - - dev_dbg(state->dev, "core: %d: prs %s@%p (%d->%d) %x@%pad\n", - state->id, msg_type_str(type), header, remoteport, - localport, bulk->actual, &bulk->dma_addr); - - dev_dbg(state->dev, "core: %d: prs:%d %cx li=%x ri=%x p=%x\n", - state->id, localport, - (type == VCHIQ_MSG_BULK_RX_DONE) ? 'r' : 't', - queue->local_insert, queue->remote_insert, queue->process); - - DEBUG_TRACE(PARSE_LINE); - WARN_ON(queue->process == queue->local_insert); - vchiq_complete_bulk(service->instance, bulk); - queue->process++; - mutex_unlock(&service->bulk_mutex); - DEBUG_TRACE(PARSE_LINE); - notify_bulks(service, queue, RETRY_POLL); - DEBUG_TRACE(PARSE_LINE); - } - break; - case VCHIQ_MSG_PADDING: - dev_dbg(state->dev, "core: %d: prs PADDING@%p,%x\n", - state->id, header, size); - break; - case VCHIQ_MSG_PAUSE: - /* If initiated, signal the application thread */ - dev_dbg(state->dev, "core: %d: prs PAUSE@%p,%x\n", - state->id, header, size); - if (state->conn_state == VCHIQ_CONNSTATE_PAUSED) { - dev_err(state->dev, "core: %d: PAUSE received in state PAUSED\n", - state->id); - break; - } - if (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT) { - /* Send a PAUSE in response */ - if (queue_message(state, NULL, MAKE_PAUSE, NULL, NULL, 0, - QMFLAGS_NO_MUTEX_UNLOCK) == -EINTR) - goto bail_not_ready; - } - /* At this point slot_mutex is held */ - vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSED); - break; - case VCHIQ_MSG_RESUME: - dev_dbg(state->dev, "core: %d: prs RESUME@%p,%x\n", - state->id, header, size); - /* Release the slot mutex */ - mutex_unlock(&state->slot_mutex); - vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); - break; - - case VCHIQ_MSG_REMOTE_USE: - vchiq_on_remote_use(state); - break; - case VCHIQ_MSG_REMOTE_RELEASE: - vchiq_on_remote_release(state); - break; - case VCHIQ_MSG_REMOTE_USE_ACTIVE: - break; - - default: - dev_err(state->dev, "core: %d: prs invalid msgid %x@%p,%x\n", - state->id, msgid, header, size); - WARN(1, "invalid message\n"); - break; - } - -skip_message: - ret = size; - -bail_not_ready: - if (service) - vchiq_service_put(service); - - return ret; -} - -/* Called by the slot handler thread */ -static void -parse_rx_slots(struct vchiq_state *state) -{ - struct vchiq_shared_state *remote = state->remote; - int tx_pos; - - DEBUG_INITIALISE(state->local); - - tx_pos = remote->tx_pos; - - while (state->rx_pos != tx_pos) { - struct vchiq_header *header; - int size; - - DEBUG_TRACE(PARSE_LINE); - if (!state->rx_data) { - int rx_index; - - WARN_ON(state->rx_pos & VCHIQ_SLOT_MASK); - rx_index = remote->slot_queue[ - SLOT_QUEUE_INDEX_FROM_POS_MASKED(state->rx_pos)]; - state->rx_data = (char *)SLOT_DATA_FROM_INDEX(state, - rx_index); - state->rx_info = SLOT_INFO_FROM_INDEX(state, rx_index); - - /* - * Initialise use_count to one, and increment - * release_count at the end of the slot to avoid - * releasing the slot prematurely. - */ - state->rx_info->use_count = 1; - state->rx_info->release_count = 0; - } - - header = (struct vchiq_header *)(state->rx_data + - (state->rx_pos & VCHIQ_SLOT_MASK)); - size = parse_message(state, header); - if (size < 0) - return; - - state->rx_pos += calc_stride(size); - - DEBUG_TRACE(PARSE_LINE); - /* - * Perform some housekeeping when the end of the slot is - * reached. - */ - if ((state->rx_pos & VCHIQ_SLOT_MASK) == 0) { - /* Remove the extra reference count. */ - release_slot(state, state->rx_info, NULL, NULL); - state->rx_data = NULL; - } - } -} - -/** - * handle_poll() - handle service polling and other rare conditions - * @state: vchiq state struct - * - * Context: Process context - * - * Return: - * * 0 - poll handled successful - * * -EAGAIN - retry later - */ -static int -handle_poll(struct vchiq_state *state) -{ - switch (state->conn_state) { - case VCHIQ_CONNSTATE_CONNECTED: - /* Poll the services as requested */ - poll_services(state); - break; - - case VCHIQ_CONNSTATE_PAUSING: - if (queue_message(state, NULL, MAKE_PAUSE, NULL, NULL, 0, - QMFLAGS_NO_MUTEX_UNLOCK) != -EINTR) { - vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSE_SENT); - } else { - /* Retry later */ - return -EAGAIN; - } - break; - - case VCHIQ_CONNSTATE_RESUMING: - if (queue_message(state, NULL, MAKE_RESUME, NULL, NULL, 0, - QMFLAGS_NO_MUTEX_LOCK) != -EINTR) { - vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); - } else { - /* - * This should really be impossible, - * since the PAUSE should have flushed - * through outstanding messages. - */ - dev_err(state->dev, "core: Failed to send RESUME message\n"); - } - break; - default: - break; - } - - return 0; -} - -/* Called by the slot handler thread */ -static int -slot_handler_func(void *v) -{ - struct vchiq_state *state = v; - struct vchiq_shared_state *local = state->local; - int ret; - - DEBUG_INITIALISE(local); - - while (!kthread_should_stop()) { - DEBUG_COUNT(SLOT_HANDLER_COUNT); - DEBUG_TRACE(SLOT_HANDLER_LINE); - ret = remote_event_wait(&state->trigger_event, &local->trigger); - if (ret) - return ret; - - /* Ensure that reads don't overtake the remote_event_wait. */ - rmb(); - - DEBUG_TRACE(SLOT_HANDLER_LINE); - if (state->poll_needed) { - state->poll_needed = 0; - - /* - * Handle service polling and other rare conditions here - * out of the mainline code - */ - if (handle_poll(state) == -EAGAIN) - state->poll_needed = 1; - } - - DEBUG_TRACE(SLOT_HANDLER_LINE); - parse_rx_slots(state); - } - return 0; -} - -/* Called by the recycle thread */ -static int -recycle_func(void *v) -{ - struct vchiq_state *state = v; - struct vchiq_shared_state *local = state->local; - u32 *found; - size_t length; - int ret; - - length = sizeof(*found) * BITSET_SIZE(VCHIQ_MAX_SERVICES); - - found = kmalloc_array(BITSET_SIZE(VCHIQ_MAX_SERVICES), sizeof(*found), - GFP_KERNEL); - if (!found) - return -ENOMEM; - - while (!kthread_should_stop()) { - ret = remote_event_wait(&state->recycle_event, &local->recycle); - if (ret) - return ret; - - process_free_queue(state, found, length); - } - return 0; -} - -/* Called by the sync thread */ -static int -sync_func(void *v) -{ - struct vchiq_state *state = v; - struct vchiq_shared_state *local = state->local; - struct vchiq_header *header = - (struct vchiq_header *)SLOT_DATA_FROM_INDEX(state, - state->remote->slot_sync); - int svc_fourcc; - int ret; - - while (!kthread_should_stop()) { - struct vchiq_service *service; - int msgid, size; - int type; - unsigned int localport, remoteport; - - ret = remote_event_wait(&state->sync_trigger_event, &local->sync_trigger); - if (ret) - return ret; - - /* Ensure that reads don't overtake the remote_event_wait. */ - rmb(); - - msgid = header->msgid; - size = header->size; - type = VCHIQ_MSG_TYPE(msgid); - localport = VCHIQ_MSG_DSTPORT(msgid); - remoteport = VCHIQ_MSG_SRCPORT(msgid); - - service = find_service_by_port(state, localport); - - if (!service) { - dev_err(state->dev, - "sync: %d: sf %s@%p (%d->%d) - invalid/closed service %d\n", - state->id, msg_type_str(type), header, remoteport, - localport, localport); - release_message_sync(state, header); - continue; - } - - svc_fourcc = service->base.fourcc; - - dev_dbg(state->dev, "sync: Rcvd Msg %s from %p4cc s:%d d:%d len:%d\n", - msg_type_str(type), &svc_fourcc, remoteport, localport, size); - if (size > 0) - vchiq_log_dump_mem(state->dev, "Rcvd", 0, header->data, min(16, size)); - - switch (type) { - case VCHIQ_MSG_OPENACK: - if (size >= sizeof(struct vchiq_openack_payload)) { - const struct vchiq_openack_payload *payload = - (struct vchiq_openack_payload *) - header->data; - service->peer_version = payload->version; - } - dev_err(state->dev, "sync: %d: sf OPENACK@%p,%x (%d->%d) v:%d\n", - state->id, header, size, remoteport, localport, - service->peer_version); - if (service->srvstate == VCHIQ_SRVSTATE_OPENING) { - service->remoteport = remoteport; - set_service_state(service, VCHIQ_SRVSTATE_OPENSYNC); - service->sync = 1; - complete(&service->remove_event); - } - release_message_sync(state, header); - break; - - case VCHIQ_MSG_DATA: - dev_dbg(state->dev, "sync: %d: sf DATA@%p,%x (%d->%d)\n", - state->id, header, size, remoteport, localport); - - if ((service->remoteport == remoteport) && - (service->srvstate == VCHIQ_SRVSTATE_OPENSYNC)) { - if (make_service_callback(service, VCHIQ_MESSAGE_AVAILABLE, header, - NULL) == -EAGAIN) - dev_err(state->dev, - "sync: error: synchronous callback to service %d returns -EAGAIN\n", - localport); - } - break; - - default: - dev_err(state->dev, "sync: error: %d: sf unexpected msgid %x@%p,%x\n", - state->id, msgid, header, size); - release_message_sync(state, header); - break; - } - - vchiq_service_put(service); - } - - return 0; -} - -inline const char * -get_conn_state_name(enum vchiq_connstate conn_state) -{ - return conn_state_names[conn_state]; -} - -struct vchiq_slot_zero * -vchiq_init_slots(struct device *dev, void *mem_base, int mem_size) -{ - int mem_align = - (int)((VCHIQ_SLOT_SIZE - (long)mem_base) & VCHIQ_SLOT_MASK); - struct vchiq_slot_zero *slot_zero = - (struct vchiq_slot_zero *)(mem_base + mem_align); - int num_slots = (mem_size - mem_align) / VCHIQ_SLOT_SIZE; - int first_data_slot = VCHIQ_SLOT_ZERO_SLOTS; - - check_sizes(); - - /* Ensure there is enough memory to run an absolutely minimum system */ - num_slots -= first_data_slot; - - if (num_slots < 4) { - dev_err(dev, "core: %s: Insufficient memory %x bytes\n", - __func__, mem_size); - return NULL; - } - - memset(slot_zero, 0, sizeof(struct vchiq_slot_zero)); - - slot_zero->magic = VCHIQ_MAGIC; - slot_zero->version = VCHIQ_VERSION; - slot_zero->version_min = VCHIQ_VERSION_MIN; - slot_zero->slot_zero_size = sizeof(struct vchiq_slot_zero); - slot_zero->slot_size = VCHIQ_SLOT_SIZE; - slot_zero->max_slots = VCHIQ_MAX_SLOTS; - slot_zero->max_slots_per_side = VCHIQ_MAX_SLOTS_PER_SIDE; - - slot_zero->master.slot_sync = first_data_slot; - slot_zero->master.slot_first = first_data_slot + 1; - slot_zero->master.slot_last = first_data_slot + (num_slots / 2) - 1; - slot_zero->slave.slot_sync = first_data_slot + (num_slots / 2); - slot_zero->slave.slot_first = first_data_slot + (num_slots / 2) + 1; - slot_zero->slave.slot_last = first_data_slot + num_slots - 1; - - return slot_zero; -} - -int -vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero, struct device *dev) -{ - struct vchiq_shared_state *local; - struct vchiq_shared_state *remote; - char threadname[16]; - int i, ret; - - local = &slot_zero->slave; - remote = &slot_zero->master; - - if (local->initialised) { - if (remote->initialised) - dev_err(dev, "local state has already been initialised\n"); - else - dev_err(dev, "master/slave mismatch two slaves\n"); - - return -EINVAL; - } - - memset(state, 0, sizeof(struct vchiq_state)); - - state->dev = dev; - - /* - * initialize shared state pointers - */ - - state->local = local; - state->remote = remote; - state->slot_data = (struct vchiq_slot *)slot_zero; - - /* - * initialize events and mutexes - */ - - init_completion(&state->connect); - mutex_init(&state->mutex); - mutex_init(&state->slot_mutex); - mutex_init(&state->recycle_mutex); - mutex_init(&state->sync_mutex); - - spin_lock_init(&state->msg_queue_spinlock); - spin_lock_init(&state->bulk_waiter_spinlock); - spin_lock_init(&state->quota_spinlock); - - init_completion(&state->slot_available_event); - init_completion(&state->data_quota_event); - - state->slot_queue_available = 0; - - for (i = 0; i < VCHIQ_MAX_SERVICES; i++) { - struct vchiq_service_quota *quota = &state->service_quotas[i]; - - init_completion("a->quota_event); - } - - for (i = local->slot_first; i <= local->slot_last; i++) { - local->slot_queue[state->slot_queue_available] = i; - state->slot_queue_available++; - complete(&state->slot_available_event); - } - - state->default_slot_quota = state->slot_queue_available / 2; - state->default_message_quota = - min_t(unsigned short, state->default_slot_quota * 256, ~0); - - state->previous_data_index = -1; - state->data_use_count = 0; - state->data_quota = state->slot_queue_available - 1; - - remote_event_create(&state->trigger_event, &local->trigger); - local->tx_pos = 0; - remote_event_create(&state->recycle_event, &local->recycle); - local->slot_queue_recycle = state->slot_queue_available; - remote_event_create(&state->sync_trigger_event, &local->sync_trigger); - remote_event_create(&state->sync_release_event, &local->sync_release); - - /* At start-of-day, the slot is empty and available */ - ((struct vchiq_header *) - SLOT_DATA_FROM_INDEX(state, local->slot_sync))->msgid = - VCHIQ_MSGID_PADDING; - remote_event_signal_local(&state->sync_release_event, &local->sync_release); - - local->debug[DEBUG_ENTRIES] = DEBUG_MAX; - - ret = vchiq_platform_init_state(state); - if (ret) - return ret; - - /* - * bring up slot handler thread - */ - snprintf(threadname, sizeof(threadname), "vchiq-slot/%d", state->id); - state->slot_handler_thread = kthread_create(&slot_handler_func, (void *)state, threadname); - - if (IS_ERR(state->slot_handler_thread)) { - dev_err(state->dev, "couldn't create thread %s\n", threadname); - return PTR_ERR(state->slot_handler_thread); - } - set_user_nice(state->slot_handler_thread, -19); - - snprintf(threadname, sizeof(threadname), "vchiq-recy/%d", state->id); - state->recycle_thread = kthread_create(&recycle_func, (void *)state, threadname); - if (IS_ERR(state->recycle_thread)) { - dev_err(state->dev, "couldn't create thread %s\n", threadname); - ret = PTR_ERR(state->recycle_thread); - goto fail_free_handler_thread; - } - set_user_nice(state->recycle_thread, -19); - - snprintf(threadname, sizeof(threadname), "vchiq-sync/%d", state->id); - state->sync_thread = kthread_create(&sync_func, (void *)state, threadname); - if (IS_ERR(state->sync_thread)) { - dev_err(state->dev, "couldn't create thread %s\n", threadname); - ret = PTR_ERR(state->sync_thread); - goto fail_free_recycle_thread; - } - set_user_nice(state->sync_thread, -20); - - wake_up_process(state->slot_handler_thread); - wake_up_process(state->recycle_thread); - wake_up_process(state->sync_thread); - - /* Indicate readiness to the other side */ - local->initialised = 1; - - return 0; - -fail_free_recycle_thread: - kthread_stop(state->recycle_thread); -fail_free_handler_thread: - kthread_stop(state->slot_handler_thread); - - return ret; -} - -void vchiq_msg_queue_push(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_header *header) -{ - struct vchiq_service *service = find_service_by_handle(instance, handle); - int pos; - - if (!service) - return; - - while (service->msg_queue_write == service->msg_queue_read + - VCHIQ_MAX_SLOTS) { - if (wait_for_completion_interruptible(&service->msg_queue_pop)) - flush_signals(current); - } - - pos = service->msg_queue_write & (VCHIQ_MAX_SLOTS - 1); - service->msg_queue_write++; - service->msg_queue[pos] = header; - - complete(&service->msg_queue_push); -} -EXPORT_SYMBOL(vchiq_msg_queue_push); - -struct vchiq_header *vchiq_msg_hold(struct vchiq_instance *instance, unsigned int handle) -{ - struct vchiq_service *service = find_service_by_handle(instance, handle); - struct vchiq_header *header; - int pos; - - if (!service) - return NULL; - - if (service->msg_queue_write == service->msg_queue_read) - return NULL; - - while (service->msg_queue_write == service->msg_queue_read) { - if (wait_for_completion_interruptible(&service->msg_queue_push)) - flush_signals(current); - } - - pos = service->msg_queue_read & (VCHIQ_MAX_SLOTS - 1); - service->msg_queue_read++; - header = service->msg_queue[pos]; - - complete(&service->msg_queue_pop); - - return header; -} -EXPORT_SYMBOL(vchiq_msg_hold); - -static int vchiq_validate_params(struct vchiq_state *state, - const struct vchiq_service_params_kernel *params) -{ - if (!params->callback || !params->fourcc) { - dev_err(state->dev, "Can't add service, invalid params\n"); - return -EINVAL; - } - - return 0; -} - -/* Called from application thread when a client or server service is created. */ -struct vchiq_service * -vchiq_add_service_internal(struct vchiq_state *state, - const struct vchiq_service_params_kernel *params, - int srvstate, struct vchiq_instance *instance, - void (*userdata_term)(void *userdata)) -{ - struct vchiq_service *service; - struct vchiq_service __rcu **pservice = NULL; - struct vchiq_service_quota *quota; - int ret; - int i; - - ret = vchiq_validate_params(state, params); - if (ret) - return NULL; - - service = kzalloc(sizeof(*service), GFP_KERNEL); - if (!service) - return service; - - service->base.fourcc = params->fourcc; - service->base.callback = params->callback; - service->base.userdata = params->userdata; - service->handle = VCHIQ_SERVICE_HANDLE_INVALID; - kref_init(&service->ref_count); - service->srvstate = VCHIQ_SRVSTATE_FREE; - service->userdata_term = userdata_term; - service->localport = VCHIQ_PORT_FREE; - service->remoteport = VCHIQ_PORT_FREE; - - service->public_fourcc = (srvstate == VCHIQ_SRVSTATE_OPENING) ? - VCHIQ_FOURCC_INVALID : params->fourcc; - service->auto_close = 1; - atomic_set(&service->poll_flags, 0); - service->version = params->version; - service->version_min = params->version_min; - service->state = state; - service->instance = instance; - init_completion(&service->remove_event); - init_completion(&service->bulk_remove_event); - init_completion(&service->msg_queue_pop); - init_completion(&service->msg_queue_push); - mutex_init(&service->bulk_mutex); - - /* - * Although it is perfectly possible to use a spinlock - * to protect the creation of services, it is overkill as it - * disables interrupts while the array is searched. - * The only danger is of another thread trying to create a - * service - service deletion is safe. - * Therefore it is preferable to use state->mutex which, - * although slower to claim, doesn't block interrupts while - * it is held. - */ - - mutex_lock(&state->mutex); - - /* Prepare to use a previously unused service */ - if (state->unused_service < VCHIQ_MAX_SERVICES) - pservice = &state->services[state->unused_service]; - - if (srvstate == VCHIQ_SRVSTATE_OPENING) { - for (i = 0; i < state->unused_service; i++) { - if (!rcu_access_pointer(state->services[i])) { - pservice = &state->services[i]; - break; - } - } - } else { - rcu_read_lock(); - for (i = (state->unused_service - 1); i >= 0; i--) { - struct vchiq_service *srv; - - srv = rcu_dereference(state->services[i]); - if (!srv) { - pservice = &state->services[i]; - } else if ((srv->public_fourcc == params->fourcc) && - ((srv->instance != instance) || - (srv->base.callback != params->callback))) { - /* - * There is another server using this - * fourcc which doesn't match. - */ - pservice = NULL; - break; - } - } - rcu_read_unlock(); - } - - if (pservice) { - service->localport = (pservice - state->services); - if (!handle_seq) - handle_seq = VCHIQ_MAX_STATES * - VCHIQ_MAX_SERVICES; - service->handle = handle_seq | - (state->id * VCHIQ_MAX_SERVICES) | - service->localport; - handle_seq += VCHIQ_MAX_STATES * VCHIQ_MAX_SERVICES; - rcu_assign_pointer(*pservice, service); - if (pservice == &state->services[state->unused_service]) - state->unused_service++; - } - - mutex_unlock(&state->mutex); - - if (!pservice) { - kfree(service); - return NULL; - } - - quota = &state->service_quotas[service->localport]; - quota->slot_quota = state->default_slot_quota; - quota->message_quota = state->default_message_quota; - if (quota->slot_use_count == 0) - quota->previous_tx_index = - SLOT_QUEUE_INDEX_FROM_POS(state->local_tx_pos) - - 1; - - /* Bring this service online */ - set_service_state(service, srvstate); - - dev_dbg(state->dev, "core_msg: %s Service %p4cc SrcPort:%d\n", - (srvstate == VCHIQ_SRVSTATE_OPENING) ? "Open" : "Add", - ¶ms->fourcc, service->localport); - - /* Don't unlock the service - leave it with a ref_count of 1. */ - - return service; -} - -int -vchiq_open_service_internal(struct vchiq_service *service, int client_id) -{ - struct vchiq_open_payload payload = { - service->base.fourcc, - client_id, - service->version, - service->version_min - }; - int status = 0; - - service->client_id = client_id; - vchiq_use_service_internal(service); - status = queue_message(service->state, - NULL, MAKE_OPEN(service->localport), - memcpy_copy_callback, - &payload, - sizeof(payload), - QMFLAGS_IS_BLOCKING); - - if (status) - return status; - - /* Wait for the ACK/NAK */ - if (wait_for_completion_interruptible(&service->remove_event)) { - status = -EAGAIN; - vchiq_release_service_internal(service); - } else if ((service->srvstate != VCHIQ_SRVSTATE_OPEN) && - (service->srvstate != VCHIQ_SRVSTATE_OPENSYNC)) { - if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) - dev_err(service->state->dev, - "core: %d: osi - srvstate = %s (ref %u)\n", - service->state->id, srvstate_names[service->srvstate], - kref_read(&service->ref_count)); - status = -EINVAL; - VCHIQ_SERVICE_STATS_INC(service, error_count); - vchiq_release_service_internal(service); - } - - return status; -} - -static void -release_service_messages(struct vchiq_service *service) -{ - struct vchiq_state *state = service->state; - int slot_last = state->remote->slot_last; - int i; - - /* Release any claimed messages aimed at this service */ - - if (service->sync) { - struct vchiq_header *header = - (struct vchiq_header *)SLOT_DATA_FROM_INDEX(state, - state->remote->slot_sync); - if (VCHIQ_MSG_DSTPORT(header->msgid) == service->localport) - release_message_sync(state, header); - - return; - } - - for (i = state->remote->slot_first; i <= slot_last; i++) { - struct vchiq_slot_info *slot_info = - SLOT_INFO_FROM_INDEX(state, i); - unsigned int pos, end; - char *data; - - if (slot_info->release_count == slot_info->use_count) - continue; - - data = (char *)SLOT_DATA_FROM_INDEX(state, i); - end = VCHIQ_SLOT_SIZE; - if (data == state->rx_data) - /* - * This buffer is still being read from - stop - * at the current read position - */ - end = state->rx_pos & VCHIQ_SLOT_MASK; - - pos = 0; - - while (pos < end) { - struct vchiq_header *header = - (struct vchiq_header *)(data + pos); - int msgid = header->msgid; - int port = VCHIQ_MSG_DSTPORT(msgid); - - if ((port == service->localport) && (msgid & VCHIQ_MSGID_CLAIMED)) { - dev_dbg(state->dev, "core: fsi - hdr %p\n", header); - release_slot(state, slot_info, header, NULL); - } - pos += calc_stride(header->size); - if (pos > VCHIQ_SLOT_SIZE) { - dev_err(state->dev, - "core: fsi - pos %x: header %p, msgid %x, header->msgid %x, header->size %x\n", - pos, header, msgid, header->msgid, header->size); - WARN(1, "invalid slot position\n"); - } - } - } -} - -static int -do_abort_bulks(struct vchiq_service *service) -{ - int status; - - /* Abort any outstanding bulk transfers */ - if (mutex_lock_killable(&service->bulk_mutex)) - return 0; - abort_outstanding_bulks(service, &service->bulk_tx); - abort_outstanding_bulks(service, &service->bulk_rx); - mutex_unlock(&service->bulk_mutex); - - status = notify_bulks(service, &service->bulk_tx, NO_RETRY_POLL); - if (status) - return 0; - - status = notify_bulks(service, &service->bulk_rx, NO_RETRY_POLL); - return !status; -} - -static int -close_service_complete(struct vchiq_service *service, int failstate) -{ - int status; - int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); - int newstate; - - switch (service->srvstate) { - case VCHIQ_SRVSTATE_OPEN: - case VCHIQ_SRVSTATE_CLOSESENT: - case VCHIQ_SRVSTATE_CLOSERECVD: - if (is_server) { - if (service->auto_close) { - service->client_id = 0; - service->remoteport = VCHIQ_PORT_FREE; - newstate = VCHIQ_SRVSTATE_LISTENING; - } else { - newstate = VCHIQ_SRVSTATE_CLOSEWAIT; - } - } else { - newstate = VCHIQ_SRVSTATE_CLOSED; - } - set_service_state(service, newstate); - break; - case VCHIQ_SRVSTATE_LISTENING: - break; - default: - dev_err(service->state->dev, "core: (%x) called in state %s\n", - service->handle, srvstate_names[service->srvstate]); - WARN(1, "%s in unexpected state\n", __func__); - return -EINVAL; - } - - status = make_service_callback(service, VCHIQ_SERVICE_CLOSED, NULL, NULL); - - if (status != -EAGAIN) { - int uc = service->service_use_count; - int i; - /* Complete the close process */ - for (i = 0; i < uc; i++) - /* - * cater for cases where close is forced and the - * client may not close all it's handles - */ - vchiq_release_service_internal(service); - - service->client_id = 0; - service->remoteport = VCHIQ_PORT_FREE; - - if (service->srvstate == VCHIQ_SRVSTATE_CLOSED) { - vchiq_free_service_internal(service); - } else if (service->srvstate != VCHIQ_SRVSTATE_CLOSEWAIT) { - if (is_server) - service->closing = 0; - - complete(&service->remove_event); - } - } else { - set_service_state(service, failstate); - } - - return status; -} - -/* - * Prepares a bulk transfer to be queued. The function is interruptible and is - * intended to be called from user threads. It may return -EAGAIN to indicate - * that a signal has been received and the call should be retried after being - * returned to user context. - */ -static int -vchiq_bulk_xfer_queue_msg_killable(struct vchiq_service *service, - struct vchiq_bulk *bulk_params) -{ - struct vchiq_bulk_queue *queue; - struct bulk_waiter *bulk_waiter = NULL; - struct vchiq_bulk *bulk; - struct vchiq_state *state = service->state; - const char dir_char = (bulk_params->dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r'; - const int dir_msgtype = (bulk_params->dir == VCHIQ_BULK_TRANSMIT) ? - VCHIQ_MSG_BULK_TX : VCHIQ_MSG_BULK_RX; - int status = -EINVAL; - int payload[2]; - - if (bulk_params->mode == VCHIQ_BULK_MODE_BLOCKING) { - bulk_waiter = bulk_params->waiter; - init_completion(&bulk_waiter->event); - bulk_waiter->actual = 0; - bulk_waiter->bulk = NULL; - } - - queue = (bulk_params->dir == VCHIQ_BULK_TRANSMIT) ? - &service->bulk_tx : &service->bulk_rx; - - if (mutex_lock_killable(&service->bulk_mutex)) - return -EINTR; - - if (queue->local_insert == queue->remove + VCHIQ_NUM_SERVICE_BULKS) { - VCHIQ_SERVICE_STATS_INC(service, bulk_stalls); - do { - mutex_unlock(&service->bulk_mutex); - if (wait_for_completion_killable(&service->bulk_remove_event)) - return -EINTR; - if (mutex_lock_killable(&service->bulk_mutex)) - return -EINTR; - } while (queue->local_insert == queue->remove + - VCHIQ_NUM_SERVICE_BULKS); - } - - bulk = &queue->bulks[BULK_INDEX(queue->local_insert)]; - - /* Initiliaze the 'bulk' slot with bulk parameters passed in. */ - bulk->mode = bulk_params->mode; - bulk->dir = bulk_params->dir; - bulk->waiter = bulk_params->waiter; - bulk->cb_data = bulk_params->cb_data; - bulk->cb_userdata = bulk_params->cb_userdata; - bulk->size = bulk_params->size; - bulk->offset = bulk_params->offset; - bulk->uoffset = bulk_params->uoffset; - bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED; - - if (vchiq_prepare_bulk_data(service->instance, bulk)) - goto unlock_error_exit; - - /* - * Ensure that the bulk data record is visible to the peer - * before proceeding. - */ - wmb(); - - dev_dbg(state->dev, "core: %d: bt (%d->%d) %cx %x@%pad %p\n", - state->id, service->localport, service->remoteport, - dir_char, bulk->size, &bulk->dma_addr, bulk->cb_data); - - /* - * The slot mutex must be held when the service is being closed, so - * claim it here to ensure that isn't happening - */ - if (mutex_lock_killable(&state->slot_mutex)) { - status = -EINTR; - goto cancel_bulk_error_exit; - } - - if (service->srvstate != VCHIQ_SRVSTATE_OPEN) - goto unlock_both_error_exit; - - payload[0] = lower_32_bits(bulk->dma_addr); - payload[1] = bulk->size; - status = queue_message(state, - NULL, - VCHIQ_MAKE_MSG(dir_msgtype, - service->localport, - service->remoteport), - memcpy_copy_callback, - &payload, - sizeof(payload), - QMFLAGS_IS_BLOCKING | - QMFLAGS_NO_MUTEX_LOCK | - QMFLAGS_NO_MUTEX_UNLOCK); - if (status) - goto unlock_both_error_exit; - - queue->local_insert++; - - mutex_unlock(&state->slot_mutex); - mutex_unlock(&service->bulk_mutex); - - dev_dbg(state->dev, "core: %d: bt:%d %cx li=%x ri=%x p=%x\n", - state->id, service->localport, dir_char, queue->local_insert, - queue->remote_insert, queue->process); - - if (bulk_waiter) { - bulk_waiter->bulk = bulk; - if (wait_for_completion_killable(&bulk_waiter->event)) - status = -EINTR; - else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED) - status = -EINVAL; - } - - return status; - -unlock_both_error_exit: - mutex_unlock(&state->slot_mutex); -cancel_bulk_error_exit: - vchiq_complete_bulk(service->instance, bulk); -unlock_error_exit: - mutex_unlock(&service->bulk_mutex); - - return status; -} - -/* Called by the slot handler */ -int -vchiq_close_service_internal(struct vchiq_service *service, int close_recvd) -{ - struct vchiq_state *state = service->state; - int status = 0; - int is_server = (service->public_fourcc != VCHIQ_FOURCC_INVALID); - int close_id = MAKE_CLOSE(service->localport, - VCHIQ_MSG_DSTPORT(service->remoteport)); - - dev_dbg(state->dev, "core: %d: csi:%d,%d (%s)\n", - service->state->id, service->localport, close_recvd, - srvstate_names[service->srvstate]); - - switch (service->srvstate) { - case VCHIQ_SRVSTATE_CLOSED: - case VCHIQ_SRVSTATE_HIDDEN: - case VCHIQ_SRVSTATE_LISTENING: - case VCHIQ_SRVSTATE_CLOSEWAIT: - if (close_recvd) { - dev_err(state->dev, "core: (1) called in state %s\n", - srvstate_names[service->srvstate]); - break; - } else if (!is_server) { - vchiq_free_service_internal(service); - break; - } - - if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) { - status = -EINVAL; - } else { - service->client_id = 0; - service->remoteport = VCHIQ_PORT_FREE; - if (service->srvstate == VCHIQ_SRVSTATE_CLOSEWAIT) - set_service_state(service, VCHIQ_SRVSTATE_LISTENING); - } - complete(&service->remove_event); - break; - case VCHIQ_SRVSTATE_OPENING: - if (close_recvd) { - /* The open was rejected - tell the user */ - set_service_state(service, VCHIQ_SRVSTATE_CLOSEWAIT); - complete(&service->remove_event); - } else { - /* Shutdown mid-open - let the other side know */ - status = queue_message(state, service, close_id, NULL, NULL, 0, 0); - } - break; - - case VCHIQ_SRVSTATE_OPENSYNC: - mutex_lock(&state->sync_mutex); - fallthrough; - case VCHIQ_SRVSTATE_OPEN: - if (close_recvd) { - if (!do_abort_bulks(service)) - status = -EAGAIN; - } - - release_service_messages(service); - - if (!status) - status = queue_message(state, service, close_id, NULL, - NULL, 0, QMFLAGS_NO_MUTEX_UNLOCK); - - if (status) { - if (service->srvstate == VCHIQ_SRVSTATE_OPENSYNC) - mutex_unlock(&state->sync_mutex); - break; - } - - if (!close_recvd) { - /* Change the state while the mutex is still held */ - set_service_state(service, VCHIQ_SRVSTATE_CLOSESENT); - mutex_unlock(&state->slot_mutex); - if (service->sync) - mutex_unlock(&state->sync_mutex); - break; - } - - /* Change the state while the mutex is still held */ - set_service_state(service, VCHIQ_SRVSTATE_CLOSERECVD); - mutex_unlock(&state->slot_mutex); - if (service->sync) - mutex_unlock(&state->sync_mutex); - - status = close_service_complete(service, VCHIQ_SRVSTATE_CLOSERECVD); - break; - - case VCHIQ_SRVSTATE_CLOSESENT: - if (!close_recvd) - /* This happens when a process is killed mid-close */ - break; - - if (!do_abort_bulks(service)) { - status = -EAGAIN; - break; - } - - if (!status) - status = close_service_complete(service, VCHIQ_SRVSTATE_CLOSERECVD); - break; - - case VCHIQ_SRVSTATE_CLOSERECVD: - if (!close_recvd && is_server) - /* Force into LISTENING mode */ - set_service_state(service, VCHIQ_SRVSTATE_LISTENING); - status = close_service_complete(service, VCHIQ_SRVSTATE_CLOSERECVD); - break; - - default: - dev_err(state->dev, "core: (%d) called in state %s\n", - close_recvd, srvstate_names[service->srvstate]); - break; - } - - return status; -} - -/* Called from the application process upon process death */ -void -vchiq_terminate_service_internal(struct vchiq_service *service) -{ - struct vchiq_state *state = service->state; - - dev_dbg(state->dev, "core: %d: tsi - (%d<->%d)\n", - state->id, service->localport, service->remoteport); - - mark_service_closing(service); - - /* Mark the service for removal by the slot handler */ - request_poll(state, service, VCHIQ_POLL_REMOVE); -} - -/* Called from the slot handler */ -void -vchiq_free_service_internal(struct vchiq_service *service) -{ - struct vchiq_state *state = service->state; - - dev_dbg(state->dev, "core: %d: fsi - (%d)\n", state->id, service->localport); - - switch (service->srvstate) { - case VCHIQ_SRVSTATE_OPENING: - case VCHIQ_SRVSTATE_CLOSED: - case VCHIQ_SRVSTATE_HIDDEN: - case VCHIQ_SRVSTATE_LISTENING: - case VCHIQ_SRVSTATE_CLOSEWAIT: - break; - default: - dev_err(state->dev, "core: %d: fsi - (%d) in state %s\n", - state->id, service->localport, srvstate_names[service->srvstate]); - return; - } - - set_service_state(service, VCHIQ_SRVSTATE_FREE); - - complete(&service->remove_event); - - /* Release the initial lock */ - vchiq_service_put(service); -} - -int -vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instance) -{ - struct vchiq_service *service; - int status = 0; - int i; - - /* Find all services registered to this client and enable them. */ - i = 0; - while ((service = next_service_by_instance(state, instance, &i)) != NULL) { - if (service->srvstate == VCHIQ_SRVSTATE_HIDDEN) - set_service_state(service, VCHIQ_SRVSTATE_LISTENING); - vchiq_service_put(service); - } - - if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) { - status = queue_message(state, NULL, MAKE_CONNECT, NULL, NULL, 0, - QMFLAGS_IS_BLOCKING); - if (status) - return status; - - vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTING); - } - - if (state->conn_state == VCHIQ_CONNSTATE_CONNECTING) { - if (wait_for_completion_interruptible(&state->connect)) - return -EAGAIN; - - vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED); - complete(&state->connect); - } - - return status; -} - -void -vchiq_shutdown_internal(struct vchiq_state *state, struct vchiq_instance *instance) -{ - struct vchiq_service *service; - int i; - - /* Find all services registered to this client and remove them. */ - i = 0; - while ((service = next_service_by_instance(state, instance, &i)) != NULL) { - (void)vchiq_remove_service(instance, service->handle); - vchiq_service_put(service); - } -} - -int -vchiq_close_service(struct vchiq_instance *instance, unsigned int handle) -{ - /* Unregister the service */ - struct vchiq_service *service = find_service_by_handle(instance, handle); - int status = 0; - - if (!service) - return -EINVAL; - - dev_dbg(service->state->dev, "core: %d: close_service:%d\n", - service->state->id, service->localport); - - if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || - (service->srvstate == VCHIQ_SRVSTATE_LISTENING) || - (service->srvstate == VCHIQ_SRVSTATE_HIDDEN)) { - vchiq_service_put(service); - return -EINVAL; - } - - mark_service_closing(service); - - if (current == service->state->slot_handler_thread) { - status = vchiq_close_service_internal(service, NO_CLOSE_RECVD); - WARN_ON(status == -EAGAIN); - } else { - /* Mark the service for termination by the slot handler */ - request_poll(service->state, service, VCHIQ_POLL_TERMINATE); - } - - while (1) { - if (wait_for_completion_interruptible(&service->remove_event)) { - status = -EAGAIN; - break; - } - - if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || - (service->srvstate == VCHIQ_SRVSTATE_LISTENING) || - (service->srvstate == VCHIQ_SRVSTATE_OPEN)) - break; - - dev_warn(service->state->dev, - "core: %d: close_service:%d - waiting in state %s\n", - service->state->id, service->localport, - srvstate_names[service->srvstate]); - } - - if (!status && - (service->srvstate != VCHIQ_SRVSTATE_FREE) && - (service->srvstate != VCHIQ_SRVSTATE_LISTENING)) - status = -EINVAL; - - vchiq_service_put(service); - - return status; -} -EXPORT_SYMBOL(vchiq_close_service); - -int -vchiq_remove_service(struct vchiq_instance *instance, unsigned int handle) -{ - /* Unregister the service */ - struct vchiq_service *service = find_service_by_handle(instance, handle); - int status = 0; - - if (!service) - return -EINVAL; - - dev_dbg(service->state->dev, "core: %d: remove_service:%d\n", - service->state->id, service->localport); - - if (service->srvstate == VCHIQ_SRVSTATE_FREE) { - vchiq_service_put(service); - return -EINVAL; - } - - mark_service_closing(service); - - if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) || - (current == service->state->slot_handler_thread)) { - /* - * Make it look like a client, because it must be removed and - * not left in the LISTENING state. - */ - service->public_fourcc = VCHIQ_FOURCC_INVALID; - - status = vchiq_close_service_internal(service, NO_CLOSE_RECVD); - WARN_ON(status == -EAGAIN); - } else { - /* Mark the service for removal by the slot handler */ - request_poll(service->state, service, VCHIQ_POLL_REMOVE); - } - while (1) { - if (wait_for_completion_interruptible(&service->remove_event)) { - status = -EAGAIN; - break; - } - - if ((service->srvstate == VCHIQ_SRVSTATE_FREE) || - (service->srvstate == VCHIQ_SRVSTATE_OPEN)) - break; - - dev_warn(service->state->dev, - "core: %d: remove_service:%d - waiting in state %s\n", - service->state->id, service->localport, - srvstate_names[service->srvstate]); - } - - if (!status && (service->srvstate != VCHIQ_SRVSTATE_FREE)) - status = -EINVAL; - - vchiq_service_put(service); - - return status; -} - -int -vchiq_bulk_xfer_blocking(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_bulk *bulk_params) -{ - struct vchiq_service *service = find_service_by_handle(instance, handle); - int status = -EINVAL; - - if (!service) - return -EINVAL; - - if (service->srvstate != VCHIQ_SRVSTATE_OPEN) - goto error_exit; - - if (!bulk_params->offset && !bulk_params->uoffset) - goto error_exit; - - if (vchiq_check_service(service)) - goto error_exit; - - status = vchiq_bulk_xfer_queue_msg_killable(service, bulk_params); - -error_exit: - vchiq_service_put(service); - - return status; -} - -int -vchiq_bulk_xfer_callback(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_bulk *bulk_params) -{ - struct vchiq_service *service = find_service_by_handle(instance, handle); - int status = -EINVAL; - - if (!service) - return -EINVAL; - - if (bulk_params->mode != VCHIQ_BULK_MODE_CALLBACK && - bulk_params->mode != VCHIQ_BULK_MODE_NOCALLBACK) - goto error_exit; - - if (service->srvstate != VCHIQ_SRVSTATE_OPEN) - goto error_exit; - - if (!bulk_params->offset && !bulk_params->uoffset) - goto error_exit; - - if (vchiq_check_service(service)) - goto error_exit; - - status = vchiq_bulk_xfer_queue_msg_killable(service, bulk_params); - -error_exit: - vchiq_service_put(service); - - return status; -} - -/* - * This function is called by VCHIQ ioctl interface and is interruptible. - * It may receive -EAGAIN to indicate that a signal has been received - * and the call should be retried after being returned to user context. - */ -int -vchiq_bulk_xfer_waiting(struct vchiq_instance *instance, - unsigned int handle, struct bulk_waiter *waiter) -{ - struct vchiq_service *service = find_service_by_handle(instance, handle); - struct bulk_waiter *bulk_waiter; - int status = -EINVAL; - - if (!service) - return -EINVAL; - - if (!waiter) - goto error_exit; - - if (service->srvstate != VCHIQ_SRVSTATE_OPEN) - goto error_exit; - - if (vchiq_check_service(service)) - goto error_exit; - - bulk_waiter = waiter; - - vchiq_service_put(service); - - status = 0; - - if (wait_for_completion_killable(&bulk_waiter->event)) - return -EINTR; - else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED) - return -EINVAL; - - return status; - -error_exit: - vchiq_service_put(service); - - return status; -} - -int -vchiq_queue_message(struct vchiq_instance *instance, unsigned int handle, - ssize_t (*copy_callback)(void *context, void *dest, - size_t offset, size_t maxsize), - void *context, - size_t size) -{ - struct vchiq_service *service = find_service_by_handle(instance, handle); - int status = -EINVAL; - int data_id; - - if (!service) - goto error_exit; - - if (vchiq_check_service(service)) - goto error_exit; - - if (!size) { - VCHIQ_SERVICE_STATS_INC(service, error_count); - goto error_exit; - } - - if (size > VCHIQ_MAX_MSG_SIZE) { - VCHIQ_SERVICE_STATS_INC(service, error_count); - goto error_exit; - } - - data_id = MAKE_DATA(service->localport, service->remoteport); - - switch (service->srvstate) { - case VCHIQ_SRVSTATE_OPEN: - status = queue_message(service->state, service, data_id, - copy_callback, context, size, - QMFLAGS_IS_BLOCKING); - break; - case VCHIQ_SRVSTATE_OPENSYNC: - status = queue_message_sync(service->state, service, data_id, - copy_callback, context, size); - break; - default: - status = -EINVAL; - break; - } - -error_exit: - if (service) - vchiq_service_put(service); - - return status; -} - -int vchiq_queue_kernel_message(struct vchiq_instance *instance, unsigned int handle, void *data, - unsigned int size) -{ - return vchiq_queue_message(instance, handle, memcpy_copy_callback, - data, size); -} -EXPORT_SYMBOL(vchiq_queue_kernel_message); - -void -vchiq_release_message(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_header *header) -{ - struct vchiq_service *service = find_service_by_handle(instance, handle); - struct vchiq_shared_state *remote; - struct vchiq_state *state; - int slot_index; - - if (!service) - return; - - state = service->state; - remote = state->remote; - - slot_index = SLOT_INDEX_FROM_DATA(state, (void *)header); - - if ((slot_index >= remote->slot_first) && - (slot_index <= remote->slot_last)) { - int msgid = header->msgid; - - if (msgid & VCHIQ_MSGID_CLAIMED) { - struct vchiq_slot_info *slot_info = - SLOT_INFO_FROM_INDEX(state, slot_index); - - release_slot(state, slot_info, header, service); - } - } else if (slot_index == remote->slot_sync) { - release_message_sync(state, header); - } - - vchiq_service_put(service); -} -EXPORT_SYMBOL(vchiq_release_message); - -static void -release_message_sync(struct vchiq_state *state, struct vchiq_header *header) -{ - header->msgid = VCHIQ_MSGID_PADDING; - remote_event_signal(state, &state->remote->sync_release); -} - -int -vchiq_get_peer_version(struct vchiq_instance *instance, unsigned int handle, short *peer_version) -{ - int status = -EINVAL; - struct vchiq_service *service = find_service_by_handle(instance, handle); - - if (!service) - goto exit; - - if (vchiq_check_service(service)) - goto exit; - - if (!peer_version) - goto exit; - - *peer_version = service->peer_version; - status = 0; - -exit: - if (service) - vchiq_service_put(service); - return status; -} -EXPORT_SYMBOL(vchiq_get_peer_version); - -void vchiq_get_config(struct vchiq_config *config) -{ - config->max_msg_size = VCHIQ_MAX_MSG_SIZE; - config->bulk_threshold = VCHIQ_MAX_MSG_SIZE; - config->max_outstanding_bulks = VCHIQ_NUM_SERVICE_BULKS; - config->max_services = VCHIQ_MAX_SERVICES; - config->version = VCHIQ_VERSION; - config->version_min = VCHIQ_VERSION_MIN; -} - -int -vchiq_set_service_option(struct vchiq_instance *instance, unsigned int handle, - enum vchiq_service_option option, int value) -{ - struct vchiq_service *service = find_service_by_handle(instance, handle); - struct vchiq_service_quota *quota; - int ret = -EINVAL; - - if (!service) - return -EINVAL; - - switch (option) { - case VCHIQ_SERVICE_OPTION_AUTOCLOSE: - service->auto_close = value; - ret = 0; - break; - - case VCHIQ_SERVICE_OPTION_SLOT_QUOTA: - quota = &service->state->service_quotas[service->localport]; - if (value == 0) - value = service->state->default_slot_quota; - if ((value >= quota->slot_use_count) && - (value < (unsigned short)~0)) { - quota->slot_quota = value; - if ((value >= quota->slot_use_count) && - (quota->message_quota >= quota->message_use_count)) - /* - * Signal the service that it may have - * dropped below its quota - */ - complete("a->quota_event); - ret = 0; - } - break; - - case VCHIQ_SERVICE_OPTION_MESSAGE_QUOTA: - quota = &service->state->service_quotas[service->localport]; - if (value == 0) - value = service->state->default_message_quota; - if ((value >= quota->message_use_count) && - (value < (unsigned short)~0)) { - quota->message_quota = value; - if ((value >= quota->message_use_count) && - (quota->slot_quota >= quota->slot_use_count)) - /* - * Signal the service that it may have - * dropped below its quota - */ - complete("a->quota_event); - ret = 0; - } - break; - - case VCHIQ_SERVICE_OPTION_SYNCHRONOUS: - if ((service->srvstate == VCHIQ_SRVSTATE_HIDDEN) || - (service->srvstate == VCHIQ_SRVSTATE_LISTENING)) { - service->sync = value; - ret = 0; - } - break; - - case VCHIQ_SERVICE_OPTION_TRACE: - service->trace = value; - ret = 0; - break; - - default: - break; - } - vchiq_service_put(service); - - return ret; -} - -static void -vchiq_dump_shared_state(struct seq_file *f, struct vchiq_state *state, - struct vchiq_shared_state *shared, const char *label) -{ - static const char *const debug_names[] = { - "<entries>", - "SLOT_HANDLER_COUNT", - "SLOT_HANDLER_LINE", - "PARSE_LINE", - "PARSE_HEADER", - "PARSE_MSGID", - "AWAIT_COMPLETION_LINE", - "DEQUEUE_MESSAGE_LINE", - "SERVICE_CALLBACK_LINE", - "MSG_QUEUE_FULL_COUNT", - "COMPLETION_QUEUE_FULL_COUNT" - }; - int i; - - seq_printf(f, " %s: slots %d-%d tx_pos=0x%x recycle=0x%x\n", - label, shared->slot_first, shared->slot_last, - shared->tx_pos, shared->slot_queue_recycle); - - seq_puts(f, " Slots claimed:\n"); - - for (i = shared->slot_first; i <= shared->slot_last; i++) { - struct vchiq_slot_info slot_info = - *SLOT_INFO_FROM_INDEX(state, i); - if (slot_info.use_count != slot_info.release_count) { - seq_printf(f, " %d: %d/%d\n", i, slot_info.use_count, - slot_info.release_count); - } - } - - for (i = 1; i < shared->debug[DEBUG_ENTRIES]; i++) { - seq_printf(f, " DEBUG: %s = %d(0x%x)\n", - debug_names[i], shared->debug[i], shared->debug[i]); - } -} - -static void -vchiq_dump_service_state(struct seq_file *f, struct vchiq_service *service) -{ - unsigned int ref_count; - - /*Don't include the lock just taken*/ - ref_count = kref_read(&service->ref_count) - 1; - seq_printf(f, "Service %u: %s (ref %u)", service->localport, - srvstate_names[service->srvstate], ref_count); - - if (service->srvstate != VCHIQ_SRVSTATE_FREE) { - char remoteport[30]; - struct vchiq_service_quota *quota = - &service->state->service_quotas[service->localport]; - int fourcc = service->base.fourcc; - int tx_pending, rx_pending, tx_size = 0, rx_size = 0; - - if (service->remoteport != VCHIQ_PORT_FREE) { - int len2 = scnprintf(remoteport, sizeof(remoteport), - "%u", service->remoteport); - - if (service->public_fourcc != VCHIQ_FOURCC_INVALID) - scnprintf(remoteport + len2, sizeof(remoteport) - len2, - " (client 0x%x)", service->client_id); - } else { - strscpy(remoteport, "n/a", sizeof(remoteport)); - } - - seq_printf(f, " '%p4cc' remote %s (msg use %d/%d, slot use %d/%d)\n", - &fourcc, remoteport, - quota->message_use_count, quota->message_quota, - quota->slot_use_count, quota->slot_quota); - - tx_pending = service->bulk_tx.local_insert - - service->bulk_tx.remote_insert; - if (tx_pending) { - unsigned int i = BULK_INDEX(service->bulk_tx.remove); - - tx_size = service->bulk_tx.bulks[i].size; - } - - rx_pending = service->bulk_rx.local_insert - - service->bulk_rx.remote_insert; - if (rx_pending) { - unsigned int i = BULK_INDEX(service->bulk_rx.remove); - - rx_size = service->bulk_rx.bulks[i].size; - } - - seq_printf(f, " Bulk: tx_pending=%d (size %d), rx_pending=%d (size %d)\n", - tx_pending, tx_size, rx_pending, rx_size); - - if (VCHIQ_ENABLE_STATS) { - seq_printf(f, " Ctrl: tx_count=%d, tx_bytes=%llu, rx_count=%d, rx_bytes=%llu\n", - service->stats.ctrl_tx_count, - service->stats.ctrl_tx_bytes, - service->stats.ctrl_rx_count, - service->stats.ctrl_rx_bytes); - - seq_printf(f, " Bulk: tx_count=%d, tx_bytes=%llu, rx_count=%d, rx_bytes=%llu\n", - service->stats.bulk_tx_count, - service->stats.bulk_tx_bytes, - service->stats.bulk_rx_count, - service->stats.bulk_rx_bytes); - - seq_printf(f, " %d quota stalls, %d slot stalls, %d bulk stalls, %d aborted, %d errors\n", - service->stats.quota_stalls, - service->stats.slot_stalls, - service->stats.bulk_stalls, - service->stats.bulk_aborted_count, - service->stats.error_count); - } - } - - vchiq_dump_platform_service_state(f, service); -} - -void vchiq_dump_state(struct seq_file *f, struct vchiq_state *state) -{ - int i; - - seq_printf(f, "State %d: %s\n", state->id, - conn_state_names[state->conn_state]); - - seq_printf(f, " tx_pos=0x%x(@%pK), rx_pos=0x%x(@%pK)\n", - state->local->tx_pos, - state->tx_data + (state->local_tx_pos & VCHIQ_SLOT_MASK), - state->rx_pos, - state->rx_data + (state->rx_pos & VCHIQ_SLOT_MASK)); - - seq_printf(f, " Version: %d (min %d)\n", VCHIQ_VERSION, - VCHIQ_VERSION_MIN); - - if (VCHIQ_ENABLE_STATS) { - seq_printf(f, " Stats: ctrl_tx_count=%d, ctrl_rx_count=%d, error_count=%d\n", - state->stats.ctrl_tx_count, state->stats.ctrl_rx_count, - state->stats.error_count); - } - - seq_printf(f, " Slots: %d available (%d data), %d recyclable, %d stalls (%d data)\n", - ((state->slot_queue_available * VCHIQ_SLOT_SIZE) - - state->local_tx_pos) / VCHIQ_SLOT_SIZE, - state->data_quota - state->data_use_count, - state->local->slot_queue_recycle - state->slot_queue_available, - state->stats.slot_stalls, state->stats.data_stalls); - - vchiq_dump_platform_state(f); - - vchiq_dump_shared_state(f, state, state->local, "Local"); - - vchiq_dump_shared_state(f, state, state->remote, "Remote"); - - vchiq_dump_platform_instances(state, f); - - for (i = 0; i < state->unused_service; i++) { - struct vchiq_service *service = find_service_by_port(state, i); - - if (service) { - vchiq_dump_service_state(f, service); - vchiq_service_put(service); - } - } -} - -int vchiq_send_remote_use(struct vchiq_state *state) -{ - if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) - return -ENOTCONN; - - return queue_message(state, NULL, MAKE_REMOTE_USE, NULL, NULL, 0, 0); -} - -int vchiq_send_remote_use_active(struct vchiq_state *state) -{ - if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) - return -ENOTCONN; - - return queue_message(state, NULL, MAKE_REMOTE_USE_ACTIVE, - NULL, NULL, 0, 0); -} - -void vchiq_log_dump_mem(struct device *dev, const char *label, u32 addr, - const void *void_mem, size_t num_bytes) -{ - const u8 *mem = void_mem; - size_t offset; - char line_buf[100]; - char *s; - - while (num_bytes > 0) { - s = line_buf; - - for (offset = 0; offset < 16; offset++) { - if (offset < num_bytes) - s += scnprintf(s, 4, "%02x ", mem[offset]); - else - s += scnprintf(s, 4, " "); - } - - for (offset = 0; offset < 16; offset++) { - if (offset < num_bytes) { - u8 ch = mem[offset]; - - if ((ch < ' ') || (ch > '~')) - ch = '.'; - *s++ = (char)ch; - } - } - *s++ = '\0'; - - if (label && (*label != '\0')) - dev_dbg(dev, "core: %s: %08x: %s\n", label, addr, line_buf); - else - dev_dbg(dev, "core: %s: %08x: %s\n", label, addr, line_buf); - - addr += 16; - mem += 16; - if (num_bytes > 16) - num_bytes -= 16; - else - num_bytes = 0; - } -} diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h deleted file mode 100644 index 9b4e766990a4..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h +++ /dev/null @@ -1,596 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#ifndef VCHIQ_CORE_H -#define VCHIQ_CORE_H - -#include <linux/mutex.h> -#include <linux/completion.h> -#include <linux/dma-mapping.h> -#include <linux/dev_printk.h> -#include <linux/kthread.h> -#include <linux/kref.h> -#include <linux/rcupdate.h> -#include <linux/seq_file.h> -#include <linux/spinlock_types.h> -#include <linux/wait.h> - -#include "../../include/linux/raspberrypi/vchiq.h" -#include "vchiq_cfg.h" - -/* Do this so that we can test-build the code on non-rpi systems */ -#if IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE) - -#else - -#ifndef dsb -#define dsb(a) -#endif - -#endif /* IS_ENABLED(CONFIG_RASPBERRYPI_FIRMWARE) */ - -#define VCHIQ_SERVICE_HANDLE_INVALID 0 - -#define VCHIQ_SLOT_SIZE 4096 -#define VCHIQ_MAX_MSG_SIZE (VCHIQ_SLOT_SIZE - sizeof(struct vchiq_header)) - -#define VCHIQ_SLOT_MASK (VCHIQ_SLOT_SIZE - 1) -#define VCHIQ_SLOT_QUEUE_MASK (VCHIQ_MAX_SLOTS_PER_SIDE - 1) -#define VCHIQ_SLOT_ZERO_SLOTS DIV_ROUND_UP(sizeof(struct vchiq_slot_zero), \ - VCHIQ_SLOT_SIZE) - -#define BITSET_SIZE(b) ((b + 31) >> 5) -#define BITSET_WORD(b) (b >> 5) -#define BITSET_BIT(b) (1 << (b & 31)) -#define BITSET_IS_SET(bs, b) (bs[BITSET_WORD(b)] & BITSET_BIT(b)) -#define BITSET_SET(bs, b) (bs[BITSET_WORD(b)] |= BITSET_BIT(b)) - -enum { - DEBUG_ENTRIES, -#if VCHIQ_ENABLE_DEBUG - DEBUG_SLOT_HANDLER_COUNT, - DEBUG_SLOT_HANDLER_LINE, - DEBUG_PARSE_LINE, - DEBUG_PARSE_HEADER, - DEBUG_PARSE_MSGID, - DEBUG_AWAIT_COMPLETION_LINE, - DEBUG_DEQUEUE_MESSAGE_LINE, - DEBUG_SERVICE_CALLBACK_LINE, - DEBUG_MSG_QUEUE_FULL_COUNT, - DEBUG_COMPLETION_QUEUE_FULL_COUNT, -#endif - DEBUG_MAX -}; - -#if VCHIQ_ENABLE_DEBUG - -#define DEBUG_INITIALISE(local) int *debug_ptr = (local)->debug -#define DEBUG_TRACE(d) \ - do { debug_ptr[DEBUG_ ## d] = __LINE__; dsb(sy); } while (0) -#define DEBUG_VALUE(d, v) \ - do { debug_ptr[DEBUG_ ## d] = (v); dsb(sy); } while (0) -#define DEBUG_COUNT(d) \ - do { debug_ptr[DEBUG_ ## d]++; dsb(sy); } while (0) - -#else /* VCHIQ_ENABLE_DEBUG */ - -#define DEBUG_INITIALISE(local) -#define DEBUG_TRACE(d) -#define DEBUG_VALUE(d, v) -#define DEBUG_COUNT(d) - -#endif /* VCHIQ_ENABLE_DEBUG */ - -enum vchiq_connstate { - VCHIQ_CONNSTATE_DISCONNECTED, - VCHIQ_CONNSTATE_CONNECTING, - VCHIQ_CONNSTATE_CONNECTED, - VCHIQ_CONNSTATE_PAUSING, - VCHIQ_CONNSTATE_PAUSE_SENT, - VCHIQ_CONNSTATE_PAUSED, - VCHIQ_CONNSTATE_RESUMING, - VCHIQ_CONNSTATE_PAUSE_TIMEOUT, - VCHIQ_CONNSTATE_RESUME_TIMEOUT -}; - -enum { - VCHIQ_SRVSTATE_FREE, - VCHIQ_SRVSTATE_HIDDEN, - VCHIQ_SRVSTATE_LISTENING, - VCHIQ_SRVSTATE_OPENING, - VCHIQ_SRVSTATE_OPEN, - VCHIQ_SRVSTATE_OPENSYNC, - VCHIQ_SRVSTATE_CLOSESENT, - VCHIQ_SRVSTATE_CLOSERECVD, - VCHIQ_SRVSTATE_CLOSEWAIT, - VCHIQ_SRVSTATE_CLOSED -}; - -enum vchiq_bulk_dir { - VCHIQ_BULK_TRANSMIT, - VCHIQ_BULK_RECEIVE -}; - -struct vchiq_bulk { - short mode; - short dir; - void *cb_data; - void __user *cb_userdata; - struct bulk_waiter *waiter; - dma_addr_t dma_addr; - int size; - void *remote_data; - int remote_size; - int actual; - void *offset; - void __user *uoffset; -}; - -struct vchiq_bulk_queue { - int local_insert; /* Where to insert the next local bulk */ - int remote_insert; /* Where to insert the next remote bulk (master) */ - int process; /* Bulk to transfer next */ - int remote_notify; /* Bulk to notify the remote client of next (mstr) */ - int remove; /* Bulk to notify the local client of, and remove, next */ - struct vchiq_bulk bulks[VCHIQ_NUM_SERVICE_BULKS]; -}; - -/* - * Remote events provide a way of presenting several virtual doorbells to a - * peer (ARM host to VPU) using only one physical doorbell. They can be thought - * of as a way for the peer to signal a semaphore, in this case implemented as - * a workqueue. - * - * Remote events remain signalled until acknowledged by the receiver, and they - * are non-counting. They are designed in such a way as to minimise the number - * of interrupts and avoid unnecessary waiting. - * - * A remote_event is as small data structures that live in shared memory. It - * comprises two booleans - armed and fired: - * - * The sender sets fired when they signal the receiver. - * If fired is set, the receiver has been signalled and need not wait. - * The receiver sets the armed field before they begin to wait. - * If armed is set, the receiver is waiting and wishes to be woken by interrupt. - */ -struct remote_event { - int armed; - int fired; - u32 __unused; -}; - -struct opaque_platform_state; - -struct vchiq_slot { - char data[VCHIQ_SLOT_SIZE]; -}; - -struct vchiq_slot_info { - /* Use two counters rather than one to avoid the need for a mutex. */ - short use_count; - short release_count; -}; - -struct vchiq_service { - struct vchiq_service_base base; - unsigned int handle; - struct kref ref_count; - struct rcu_head rcu; - int srvstate; - void (*userdata_term)(void *userdata); - unsigned int localport; - unsigned int remoteport; - int public_fourcc; - int client_id; - char auto_close; - char sync; - char closing; - char trace; - atomic_t poll_flags; - short version; - short version_min; - short peer_version; - - struct vchiq_state *state; - struct vchiq_instance *instance; - - int service_use_count; - - struct vchiq_bulk_queue bulk_tx; - struct vchiq_bulk_queue bulk_rx; - - struct completion remove_event; - struct completion bulk_remove_event; - struct mutex bulk_mutex; - - struct service_stats_struct { - int quota_stalls; - int slot_stalls; - int bulk_stalls; - int error_count; - int ctrl_tx_count; - int ctrl_rx_count; - int bulk_tx_count; - int bulk_rx_count; - int bulk_aborted_count; - u64 ctrl_tx_bytes; - u64 ctrl_rx_bytes; - u64 bulk_tx_bytes; - u64 bulk_rx_bytes; - } stats; - - int msg_queue_read; - int msg_queue_write; - struct completion msg_queue_pop; - struct completion msg_queue_push; - struct vchiq_header *msg_queue[VCHIQ_MAX_SLOTS]; -}; - -/* - * The quota information is outside struct vchiq_service so that it can - * be statically allocated, since for accounting reasons a service's slot - * usage is carried over between users of the same port number. - */ -struct vchiq_service_quota { - unsigned short slot_quota; - unsigned short slot_use_count; - unsigned short message_quota; - unsigned short message_use_count; - struct completion quota_event; - int previous_tx_index; -}; - -struct vchiq_shared_state { - /* A non-zero value here indicates that the content is valid. */ - int initialised; - - /* The first and last (inclusive) slots allocated to the owner. */ - int slot_first; - int slot_last; - - /* The slot allocated to synchronous messages from the owner. */ - int slot_sync; - - /* - * Signalling this event indicates that owner's slot handler thread - * should run. - */ - struct remote_event trigger; - - /* - * Indicates the byte position within the stream where the next message - * will be written. The least significant bits are an index into the - * slot. The next bits are the index of the slot in slot_queue. - */ - int tx_pos; - - /* This event should be signalled when a slot is recycled. */ - struct remote_event recycle; - - /* The slot_queue index where the next recycled slot will be written. */ - int slot_queue_recycle; - - /* This event should be signalled when a synchronous message is sent. */ - struct remote_event sync_trigger; - - /* - * This event should be signalled when a synchronous message has been - * released. - */ - struct remote_event sync_release; - - /* A circular buffer of slot indexes. */ - int slot_queue[VCHIQ_MAX_SLOTS_PER_SIDE]; - - /* Debugging state */ - int debug[DEBUG_MAX]; -}; - -struct vchiq_slot_zero { - int magic; - short version; - short version_min; - int slot_zero_size; - int slot_size; - int max_slots; - int max_slots_per_side; - int platform_data[2]; - struct vchiq_shared_state master; - struct vchiq_shared_state slave; - struct vchiq_slot_info slots[VCHIQ_MAX_SLOTS]; -}; - -struct vchiq_state { - struct device *dev; - int id; - int initialised; - enum vchiq_connstate conn_state; - short version_common; - - struct vchiq_shared_state *local; - struct vchiq_shared_state *remote; - struct vchiq_slot *slot_data; - - unsigned short default_slot_quota; - unsigned short default_message_quota; - - /* Event indicating connect message received */ - struct completion connect; - - /* Mutex protecting services */ - struct mutex mutex; - struct vchiq_instance **instance; - - /* Processes incoming messages */ - struct task_struct *slot_handler_thread; - - /* Processes recycled slots */ - struct task_struct *recycle_thread; - - /* Processes synchronous messages */ - struct task_struct *sync_thread; - - /* Local implementation of the trigger remote event */ - wait_queue_head_t trigger_event; - - /* Local implementation of the recycle remote event */ - wait_queue_head_t recycle_event; - - /* Local implementation of the sync trigger remote event */ - wait_queue_head_t sync_trigger_event; - - /* Local implementation of the sync release remote event */ - wait_queue_head_t sync_release_event; - - char *tx_data; - char *rx_data; - struct vchiq_slot_info *rx_info; - - struct mutex slot_mutex; - - struct mutex recycle_mutex; - - struct mutex sync_mutex; - - spinlock_t msg_queue_spinlock; - - spinlock_t bulk_waiter_spinlock; - - spinlock_t quota_spinlock; - - /* - * Indicates the byte position within the stream from where the next - * message will be read. The least significant bits are an index into - * the slot.The next bits are the index of the slot in - * remote->slot_queue. - */ - int rx_pos; - - /* - * A cached copy of local->tx_pos. Only write to local->tx_pos, and read - * from remote->tx_pos. - */ - int local_tx_pos; - - /* The slot_queue index of the slot to become available next. */ - int slot_queue_available; - - /* A flag to indicate if any poll has been requested */ - int poll_needed; - - /* Ths index of the previous slot used for data messages. */ - int previous_data_index; - - /* The number of slots occupied by data messages. */ - unsigned short data_use_count; - - /* The maximum number of slots to be occupied by data messages. */ - unsigned short data_quota; - - /* An array of bit sets indicating which services must be polled. */ - atomic_t poll_services[BITSET_SIZE(VCHIQ_MAX_SERVICES)]; - - /* The number of the first unused service */ - int unused_service; - - /* Signalled when a free slot becomes available. */ - struct completion slot_available_event; - - /* Signalled when a free data slot becomes available. */ - struct completion data_quota_event; - - struct state_stats_struct { - int slot_stalls; - int data_stalls; - int ctrl_tx_count; - int ctrl_rx_count; - int error_count; - } stats; - - struct vchiq_service __rcu *services[VCHIQ_MAX_SERVICES]; - struct vchiq_service_quota service_quotas[VCHIQ_MAX_SERVICES]; - struct vchiq_slot_info slot_info[VCHIQ_MAX_SLOTS]; - - struct opaque_platform_state *platform_state; -}; - -struct pagelist { - u32 length; - u16 type; - u16 offset; - u32 addrs[1]; /* N.B. 12 LSBs hold the number - * of following pages at consecutive - * addresses. - */ -}; - -struct vchiq_pagelist_info { - struct pagelist *pagelist; - size_t pagelist_buffer_size; - dma_addr_t dma_addr; - enum dma_data_direction dma_dir; - unsigned int num_pages; - unsigned int pages_need_release; - struct page **pages; - struct scatterlist *scatterlist; - unsigned int scatterlist_mapped; -}; - -static inline bool vchiq_remote_initialised(const struct vchiq_state *state) -{ - return state->remote && state->remote->initialised; -} - -struct bulk_waiter { - struct vchiq_bulk *bulk; - struct completion event; - int actual; -}; - -struct vchiq_config { - unsigned int max_msg_size; - unsigned int bulk_threshold; /* The message size above which it - * is better to use a bulk transfer - * (<= max_msg_size) - */ - unsigned int max_outstanding_bulks; - unsigned int max_services; - short version; /* The version of VCHIQ */ - short version_min; /* The minimum compatible version of VCHIQ */ -}; - -extern spinlock_t bulk_waiter_spinlock; - -extern const char * -get_conn_state_name(enum vchiq_connstate conn_state); - -extern struct vchiq_slot_zero * -vchiq_init_slots(struct device *dev, void *mem_base, int mem_size); - -extern int -vchiq_init_state(struct vchiq_state *state, struct vchiq_slot_zero *slot_zero, struct device *dev); - -extern int -vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instance); - -struct vchiq_service * -vchiq_add_service_internal(struct vchiq_state *state, - const struct vchiq_service_params_kernel *params, - int srvstate, struct vchiq_instance *instance, - void (*userdata_term)(void *userdata)); - -extern int -vchiq_open_service_internal(struct vchiq_service *service, int client_id); - -extern int -vchiq_close_service_internal(struct vchiq_service *service, int close_recvd); - -extern void -vchiq_terminate_service_internal(struct vchiq_service *service); - -extern void -vchiq_free_service_internal(struct vchiq_service *service); - -extern void -vchiq_shutdown_internal(struct vchiq_state *state, struct vchiq_instance *instance); - -extern void -remote_event_pollall(struct vchiq_state *state); - -extern int -vchiq_bulk_xfer_waiting(struct vchiq_instance *instance, unsigned int handle, - struct bulk_waiter *userdata); - -extern int -vchiq_bulk_xfer_blocking(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_bulk *bulk); - -extern int -vchiq_bulk_xfer_callback(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_bulk *bulk); - -extern void -vchiq_dump_state(struct seq_file *f, struct vchiq_state *state); - -extern void -request_poll(struct vchiq_state *state, struct vchiq_service *service, - int poll_type); - -struct vchiq_service *handle_to_service(struct vchiq_instance *instance, unsigned int handle); - -extern struct vchiq_service * -find_service_by_handle(struct vchiq_instance *instance, unsigned int handle); - -extern struct vchiq_service * -find_service_by_port(struct vchiq_state *state, unsigned int localport); - -extern struct vchiq_service * -find_service_for_instance(struct vchiq_instance *instance, unsigned int handle); - -extern struct vchiq_service * -find_closed_service_for_instance(struct vchiq_instance *instance, unsigned int handle); - -extern struct vchiq_service * -__next_service_by_instance(struct vchiq_state *state, - struct vchiq_instance *instance, - int *pidx); - -extern struct vchiq_service * -next_service_by_instance(struct vchiq_state *state, - struct vchiq_instance *instance, - int *pidx); - -extern void -vchiq_service_get(struct vchiq_service *service); - -extern void -vchiq_service_put(struct vchiq_service *service); - -extern int -vchiq_queue_message(struct vchiq_instance *instance, unsigned int handle, - ssize_t (*copy_callback)(void *context, void *dest, - size_t offset, size_t maxsize), - void *context, - size_t size); - -void vchiq_dump_platform_state(struct seq_file *f); - -void vchiq_dump_platform_instances(struct vchiq_state *state, struct seq_file *f); - -void vchiq_dump_platform_service_state(struct seq_file *f, struct vchiq_service *service); - -int vchiq_use_service_internal(struct vchiq_service *service); - -int vchiq_release_service_internal(struct vchiq_service *service); - -void vchiq_on_remote_use(struct vchiq_state *state); - -void vchiq_on_remote_release(struct vchiq_state *state); - -int vchiq_platform_init_state(struct vchiq_state *state); - -int vchiq_check_service(struct vchiq_service *service); - -int vchiq_send_remote_use(struct vchiq_state *state); - -int vchiq_send_remote_use_active(struct vchiq_state *state); - -void vchiq_platform_conn_state_changed(struct vchiq_state *state, - enum vchiq_connstate oldstate, - enum vchiq_connstate newstate); - -void vchiq_set_conn_state(struct vchiq_state *state, enum vchiq_connstate newstate); - -void vchiq_log_dump_mem(struct device *dev, const char *label, u32 addr, - const void *void_mem, size_t num_bytes); - -int vchiq_remove_service(struct vchiq_instance *instance, unsigned int service); - -int vchiq_get_client_id(struct vchiq_instance *instance, unsigned int service); - -void vchiq_get_config(struct vchiq_config *config); - -int vchiq_set_service_option(struct vchiq_instance *instance, unsigned int service, - enum vchiq_service_option option, int value); - -#endif diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c deleted file mode 100644 index d5f7f61c5626..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.c +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* - * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. - * Copyright (c) 2010-2012 Broadcom. All rights reserved. - */ - -#include <linux/debugfs.h> -#include "vchiq_core.h" -#include "vchiq_arm.h" -#include "vchiq_debugfs.h" - -#ifdef CONFIG_DEBUG_FS - -#define DEBUGFS_WRITE_BUF_SIZE 256 - -/* Global 'vchiq' debugfs and clients entry used by all instances */ -static struct dentry *vchiq_dbg_dir; -static struct dentry *vchiq_dbg_clients; - -static int debugfs_usecount_show(struct seq_file *f, void *offset) -{ - struct vchiq_instance *instance = f->private; - int use_count; - - use_count = vchiq_instance_get_use_count(instance); - seq_printf(f, "%d\n", use_count); - - return 0; -} -DEFINE_SHOW_ATTRIBUTE(debugfs_usecount); - -static int debugfs_trace_show(struct seq_file *f, void *offset) -{ - struct vchiq_instance *instance = f->private; - int trace; - - trace = vchiq_instance_get_trace(instance); - seq_printf(f, "%s\n", trace ? "Y" : "N"); - - return 0; -} - -static int vchiq_dump_show(struct seq_file *f, void *offset) -{ - struct vchiq_state *state = f->private; - - vchiq_dump_state(f, state); - - return 0; -} -DEFINE_SHOW_ATTRIBUTE(vchiq_dump); - -static int debugfs_trace_open(struct inode *inode, struct file *file) -{ - return single_open(file, debugfs_trace_show, inode->i_private); -} - -static ssize_t debugfs_trace_write(struct file *file, - const char __user *buffer, - size_t count, loff_t *ppos) -{ - struct seq_file *f = (struct seq_file *)file->private_data; - struct vchiq_instance *instance = f->private; - char firstchar; - - if (copy_from_user(&firstchar, buffer, 1)) - return -EFAULT; - - switch (firstchar) { - case 'Y': - case 'y': - case '1': - vchiq_instance_set_trace(instance, 1); - break; - case 'N': - case 'n': - case '0': - vchiq_instance_set_trace(instance, 0); - break; - default: - break; - } - - *ppos += count; - - return count; -} - -static const struct file_operations debugfs_trace_fops = { - .owner = THIS_MODULE, - .open = debugfs_trace_open, - .write = debugfs_trace_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* add an instance (process) to the debugfs entries */ -void vchiq_debugfs_add_instance(struct vchiq_instance *instance) -{ - char pidstr[16]; - struct dentry *top; - - snprintf(pidstr, sizeof(pidstr), "%d", - vchiq_instance_get_pid(instance)); - - top = debugfs_create_dir(pidstr, vchiq_dbg_clients); - - debugfs_create_file("use_count", 0444, top, instance, - &debugfs_usecount_fops); - debugfs_create_file("trace", 0644, top, instance, &debugfs_trace_fops); - - vchiq_instance_get_debugfs_node(instance)->dentry = top; -} - -void vchiq_debugfs_remove_instance(struct vchiq_instance *instance) -{ - struct vchiq_debugfs_node *node = - vchiq_instance_get_debugfs_node(instance); - - debugfs_remove_recursive(node->dentry); -} - -void vchiq_debugfs_init(struct vchiq_state *state) -{ - vchiq_dbg_dir = debugfs_create_dir("vchiq", NULL); - vchiq_dbg_clients = debugfs_create_dir("clients", vchiq_dbg_dir); - - debugfs_create_file("state", S_IFREG | 0444, vchiq_dbg_dir, state, - &vchiq_dump_fops); -} - -/* remove all the debugfs entries */ -void vchiq_debugfs_deinit(void) -{ - debugfs_remove_recursive(vchiq_dbg_dir); -} - -#else /* CONFIG_DEBUG_FS */ - -void vchiq_debugfs_init(struct vchiq_state *state) -{ -} - -void vchiq_debugfs_deinit(void) -{ -} - -void vchiq_debugfs_add_instance(struct vchiq_instance *instance) -{ -} - -void vchiq_debugfs_remove_instance(struct vchiq_instance *instance) -{ -} - -#endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h deleted file mode 100644 index b29e6693c949..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. */ - -#ifndef VCHIQ_DEBUGFS_H -#define VCHIQ_DEBUGFS_H - -struct vchiq_state; -struct vchiq_instance; - -struct vchiq_debugfs_node { - struct dentry *dentry; -}; - -void vchiq_debugfs_init(struct vchiq_state *state); - -void vchiq_debugfs_deinit(void); - -void vchiq_debugfs_add_instance(struct vchiq_instance *instance); - -void vchiq_debugfs_remove_instance(struct vchiq_instance *instance); - -#endif /* VCHIQ_DEBUGFS_H */ diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c deleted file mode 100644 index 3b20ba5c7362..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c +++ /dev/null @@ -1,1354 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -/* - * Copyright (c) 2014 Raspberry Pi (Trading) Ltd. All rights reserved. - * Copyright (c) 2010-2012 Broadcom. All rights reserved. - */ - -#include <linux/cdev.h> -#include <linux/fs.h> -#include <linux/device.h> -#include <linux/slab.h> -#include <linux/compat.h> -#include <linux/miscdevice.h> - -#include "vchiq_core.h" -#include "vchiq_ioctl.h" -#include "vchiq_arm.h" -#include "vchiq_debugfs.h" - -static const char *const ioctl_names[] = { - "CONNECT", - "SHUTDOWN", - "CREATE_SERVICE", - "REMOVE_SERVICE", - "QUEUE_MESSAGE", - "QUEUE_BULK_TRANSMIT", - "QUEUE_BULK_RECEIVE", - "AWAIT_COMPLETION", - "DEQUEUE_MESSAGE", - "GET_CLIENT_ID", - "GET_CONFIG", - "CLOSE_SERVICE", - "USE_SERVICE", - "RELEASE_SERVICE", - "SET_SERVICE_OPTION", - "DUMP_PHYS_MEM", - "LIB_VERSION", - "CLOSE_DELIVERED" -}; - -static_assert(ARRAY_SIZE(ioctl_names) == (VCHIQ_IOC_MAX + 1)); - -static void -user_service_free(void *userdata) -{ - kfree(userdata); -} - -static void close_delivered(struct user_service *user_service) -{ - dev_dbg(user_service->service->state->dev, - "arm: (handle=%x)\n", user_service->service->handle); - - if (user_service->close_pending) { - /* Allow the underlying service to be culled */ - vchiq_service_put(user_service->service); - - /* Wake the user-thread blocked in close_ or remove_service */ - complete(&user_service->close_event); - - user_service->close_pending = 0; - } -} - -struct vchiq_io_copy_callback_context { - struct vchiq_element *element; - size_t element_offset; - unsigned long elements_to_go; -}; - -static ssize_t vchiq_ioc_copy_element_data(void *context, void *dest, - size_t offset, size_t maxsize) -{ - struct vchiq_io_copy_callback_context *cc = context; - size_t total_bytes_copied = 0; - size_t bytes_this_round; - - while (total_bytes_copied < maxsize) { - if (!cc->elements_to_go) - return total_bytes_copied; - - if (!cc->element->size) { - cc->elements_to_go--; - cc->element++; - cc->element_offset = 0; - continue; - } - - bytes_this_round = min(cc->element->size - cc->element_offset, - maxsize - total_bytes_copied); - - if (copy_from_user(dest + total_bytes_copied, - cc->element->data + cc->element_offset, - bytes_this_round)) - return -EFAULT; - - cc->element_offset += bytes_this_round; - total_bytes_copied += bytes_this_round; - - if (cc->element_offset == cc->element->size) { - cc->elements_to_go--; - cc->element++; - cc->element_offset = 0; - } - } - - return maxsize; -} - -static int -vchiq_ioc_queue_message(struct vchiq_instance *instance, unsigned int handle, - struct vchiq_element *elements, unsigned long count) -{ - struct vchiq_io_copy_callback_context context; - int status = 0; - unsigned long i; - size_t total_size = 0; - - context.element = elements; - context.element_offset = 0; - context.elements_to_go = count; - - for (i = 0; i < count; i++) { - if (!elements[i].data && elements[i].size != 0) - return -EFAULT; - - total_size += elements[i].size; - } - - status = vchiq_queue_message(instance, handle, vchiq_ioc_copy_element_data, - &context, total_size); - - if (status == -EINVAL) - return -EIO; - else if (status == -EAGAIN) - return -EINTR; - return 0; -} - -static int vchiq_ioc_create_service(struct vchiq_instance *instance, - struct vchiq_create_service *args) -{ - struct user_service *user_service = NULL; - struct vchiq_service *service; - int status = 0; - struct vchiq_service_params_kernel params; - int srvstate; - - if (args->is_open && !instance->connected) - return -ENOTCONN; - - user_service = kmalloc(sizeof(*user_service), GFP_KERNEL); - if (!user_service) - return -ENOMEM; - - if (args->is_open) { - srvstate = VCHIQ_SRVSTATE_OPENING; - } else { - srvstate = instance->connected ? - VCHIQ_SRVSTATE_LISTENING : VCHIQ_SRVSTATE_HIDDEN; - } - - params = (struct vchiq_service_params_kernel) { - .fourcc = args->params.fourcc, - .callback = service_callback, - .userdata = user_service, - .version = args->params.version, - .version_min = args->params.version_min, - }; - service = vchiq_add_service_internal(instance->state, ¶ms, - srvstate, instance, - user_service_free); - if (!service) { - kfree(user_service); - return -EEXIST; - } - - user_service->service = service; - user_service->userdata = args->params.userdata; - user_service->instance = instance; - user_service->is_vchi = (args->is_vchi != 0); - user_service->dequeue_pending = 0; - user_service->close_pending = 0; - user_service->message_available_pos = instance->completion_remove - 1; - user_service->msg_insert = 0; - user_service->msg_remove = 0; - init_completion(&user_service->insert_event); - init_completion(&user_service->remove_event); - init_completion(&user_service->close_event); - - if (args->is_open) { - status = vchiq_open_service_internal(service, instance->pid); - if (status) { - vchiq_remove_service(instance, service->handle); - return (status == -EAGAIN) ? - -EINTR : -EIO; - } - } - args->handle = service->handle; - - return 0; -} - -static int vchiq_ioc_dequeue_message(struct vchiq_instance *instance, - struct vchiq_dequeue_message *args) -{ - struct user_service *user_service; - struct vchiq_service *service; - struct vchiq_header *header; - int ret; - - DEBUG_INITIALISE(instance->state->local); - DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); - service = find_service_for_instance(instance, args->handle); - if (!service) - return -EINVAL; - - user_service = (struct user_service *)service->base.userdata; - if (user_service->is_vchi == 0) { - ret = -EINVAL; - goto out; - } - - spin_lock(&service->state->msg_queue_spinlock); - if (user_service->msg_remove == user_service->msg_insert) { - if (!args->blocking) { - spin_unlock(&service->state->msg_queue_spinlock); - DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); - ret = -EWOULDBLOCK; - goto out; - } - user_service->dequeue_pending = 1; - ret = 0; - do { - spin_unlock(&service->state->msg_queue_spinlock); - DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); - if (wait_for_completion_interruptible(&user_service->insert_event)) { - dev_dbg(service->state->dev, "arm: DEQUEUE_MESSAGE interrupted\n"); - ret = -EINTR; - break; - } - spin_lock(&service->state->msg_queue_spinlock); - } while (user_service->msg_remove == user_service->msg_insert); - - if (ret) - goto out; - } - - if (WARN_ON_ONCE((int)(user_service->msg_insert - - user_service->msg_remove) < 0)) { - spin_unlock(&service->state->msg_queue_spinlock); - ret = -EINVAL; - goto out; - } - - header = user_service->msg_queue[user_service->msg_remove & - (MSG_QUEUE_SIZE - 1)]; - user_service->msg_remove++; - spin_unlock(&service->state->msg_queue_spinlock); - - complete(&user_service->remove_event); - if (!header) { - ret = -ENOTCONN; - } else if (header->size <= args->bufsize) { - /* Copy to user space if msgbuf is not NULL */ - if (!args->buf || (copy_to_user(args->buf, header->data, header->size) == 0)) { - ret = header->size; - vchiq_release_message(instance, service->handle, header); - } else { - ret = -EFAULT; - } - } else { - dev_err(service->state->dev, - "arm: header %p: bufsize %x < size %x\n", - header, args->bufsize, header->size); - WARN(1, "invalid size\n"); - ret = -EMSGSIZE; - } - DEBUG_TRACE(DEQUEUE_MESSAGE_LINE); -out: - vchiq_service_put(service); - return ret; -} - -static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance, - struct vchiq_queue_bulk_transfer *args, - enum vchiq_bulk_dir dir, - enum vchiq_bulk_mode __user *mode) -{ - struct vchiq_service *service; - struct bulk_waiter_node *waiter = NULL, *iter; - struct vchiq_bulk bulk_params = {}; - int status = 0; - int ret; - - service = find_service_for_instance(instance, args->handle); - if (!service) - return -EINVAL; - - if (args->mode == VCHIQ_BULK_MODE_BLOCKING) { - waiter = kzalloc(sizeof(*waiter), GFP_KERNEL); - if (!waiter) { - ret = -ENOMEM; - goto out; - } - - bulk_params.uoffset = args->data; - bulk_params.mode = args->mode; - bulk_params.size = args->size; - bulk_params.dir = dir; - bulk_params.waiter = &waiter->bulk_waiter; - - status = vchiq_bulk_xfer_blocking(instance, args->handle, - &bulk_params); - } else if (args->mode == VCHIQ_BULK_MODE_WAITING) { - mutex_lock(&instance->bulk_waiter_list_mutex); - list_for_each_entry(iter, &instance->bulk_waiter_list, - list) { - if (iter->pid == current->pid) { - list_del(&iter->list); - waiter = iter; - break; - } - } - mutex_unlock(&instance->bulk_waiter_list_mutex); - if (!waiter) { - dev_err(service->state->dev, - "arm: no bulk_waiter found for pid %d\n", current->pid); - ret = -ESRCH; - goto out; - } - dev_dbg(service->state->dev, "arm: found bulk_waiter %p for pid %d\n", - waiter, current->pid); - - status = vchiq_bulk_xfer_waiting(instance, args->handle, - &waiter->bulk_waiter); - } else { - bulk_params.uoffset = args->data; - bulk_params.mode = args->mode; - bulk_params.size = args->size; - bulk_params.dir = dir; - bulk_params.cb_userdata = args->userdata; - - status = vchiq_bulk_xfer_callback(instance, args->handle, - &bulk_params); - } - - if (!waiter) { - ret = 0; - goto out; - } - - if ((status != -EAGAIN) || fatal_signal_pending(current) || - !waiter->bulk_waiter.bulk) { - if (waiter->bulk_waiter.bulk) { - /* Cancel the signal when the transfer completes. */ - spin_lock(&service->state->bulk_waiter_spinlock); - waiter->bulk_waiter.bulk->waiter = NULL; - spin_unlock(&service->state->bulk_waiter_spinlock); - } - kfree(waiter); - ret = 0; - } else { - const enum vchiq_bulk_mode mode_waiting = - VCHIQ_BULK_MODE_WAITING; - waiter->pid = current->pid; - mutex_lock(&instance->bulk_waiter_list_mutex); - list_add(&waiter->list, &instance->bulk_waiter_list); - mutex_unlock(&instance->bulk_waiter_list_mutex); - dev_dbg(service->state->dev, "arm: saved bulk_waiter %p for pid %d\n", - waiter, current->pid); - - ret = put_user(mode_waiting, mode); - } -out: - vchiq_service_put(service); - if (ret) - return ret; - else if (status == -EINVAL) - return -EIO; - else if (status == -EAGAIN) - return -EINTR; - return 0; -} - -/* read a user pointer value from an array pointers in user space */ -static inline int vchiq_get_user_ptr(void __user **buf, void __user *ubuf, int index) -{ - int ret; - - if (in_compat_syscall()) { - compat_uptr_t ptr32; - compat_uptr_t __user *uptr = ubuf; - - ret = get_user(ptr32, uptr + index); - if (ret) - return ret; - - *buf = compat_ptr(ptr32); - } else { - uintptr_t ptr, __user *uptr = ubuf; - - ret = get_user(ptr, uptr + index); - - if (ret) - return ret; - - *buf = (void __user *)ptr; - } - - return 0; -} - -struct vchiq_completion_data32 { - enum vchiq_reason reason; - compat_uptr_t header; - compat_uptr_t service_userdata; - compat_uptr_t cb_data; -}; - -static int vchiq_put_completion(struct vchiq_completion_data __user *buf, - struct vchiq_completion_data *completion, - int index) -{ - struct vchiq_completion_data32 __user *buf32 = (void __user *)buf; - - if (in_compat_syscall()) { - struct vchiq_completion_data32 tmp = { - .reason = completion->reason, - .header = ptr_to_compat(completion->header), - .service_userdata = ptr_to_compat(completion->service_userdata), - .cb_data = ptr_to_compat(completion->cb_userdata), - }; - if (copy_to_user(&buf32[index], &tmp, sizeof(tmp))) - return -EFAULT; - } else { - if (copy_to_user(&buf[index], completion, sizeof(*completion))) - return -EFAULT; - } - - return 0; -} - -static int vchiq_ioc_await_completion(struct vchiq_instance *instance, - struct vchiq_await_completion *args, - int __user *msgbufcountp) -{ - int msgbufcount; - int remove; - int ret; - - DEBUG_INITIALISE(instance->state->local); - - DEBUG_TRACE(AWAIT_COMPLETION_LINE); - if (!instance->connected) - return -ENOTCONN; - - mutex_lock(&instance->completion_mutex); - - DEBUG_TRACE(AWAIT_COMPLETION_LINE); - while ((instance->completion_remove == instance->completion_insert) && !instance->closing) { - int rc; - - DEBUG_TRACE(AWAIT_COMPLETION_LINE); - mutex_unlock(&instance->completion_mutex); - rc = wait_for_completion_interruptible(&instance->insert_event); - mutex_lock(&instance->completion_mutex); - if (rc) { - DEBUG_TRACE(AWAIT_COMPLETION_LINE); - dev_dbg(instance->state->dev, "arm: AWAIT_COMPLETION interrupted\n"); - ret = -EINTR; - goto out; - } - } - DEBUG_TRACE(AWAIT_COMPLETION_LINE); - - msgbufcount = args->msgbufcount; - remove = instance->completion_remove; - - for (ret = 0; ret < args->count; ret++) { - struct vchiq_completion_data_kernel *completion; - struct vchiq_completion_data user_completion; - struct vchiq_service *service; - struct user_service *user_service; - struct vchiq_header *header; - - if (remove == instance->completion_insert) - break; - - completion = &instance->completions[remove & (MAX_COMPLETIONS - 1)]; - - /* - * A read memory barrier is needed to stop - * prefetch of a stale completion record - */ - rmb(); - - service = completion->service_userdata; - user_service = service->base.userdata; - - memset(&user_completion, 0, sizeof(user_completion)); - user_completion = (struct vchiq_completion_data) { - .reason = completion->reason, - .service_userdata = user_service->userdata, - }; - - header = completion->header; - if (header) { - void __user *msgbuf; - int msglen; - - msglen = header->size + sizeof(struct vchiq_header); - /* This must be a VCHIQ-style service */ - if (args->msgbufsize < msglen) { - dev_err(service->state->dev, - "arm: header %p: msgbufsize %x < msglen %x\n", - header, args->msgbufsize, msglen); - WARN(1, "invalid message size\n"); - if (ret == 0) - ret = -EMSGSIZE; - break; - } - if (msgbufcount <= 0) - /* Stall here for lack of a buffer for the message. */ - break; - /* Get the pointer from user space */ - msgbufcount--; - if (vchiq_get_user_ptr(&msgbuf, args->msgbufs, - msgbufcount)) { - if (ret == 0) - ret = -EFAULT; - break; - } - - /* Copy the message to user space */ - if (copy_to_user(msgbuf, header, msglen)) { - if (ret == 0) - ret = -EFAULT; - break; - } - - /* Now it has been copied, the message can be released. */ - vchiq_release_message(instance, service->handle, header); - - /* The completion must point to the msgbuf. */ - user_completion.header = msgbuf; - } - - if ((completion->reason == VCHIQ_SERVICE_CLOSED) && - !instance->use_close_delivered) - vchiq_service_put(service); - - user_completion.cb_userdata = completion->cb_userdata; - - if (vchiq_put_completion(args->buf, &user_completion, ret)) { - if (ret == 0) - ret = -EFAULT; - break; - } - - /* - * Ensure that the above copy has completed - * before advancing the remove pointer. - */ - mb(); - remove++; - instance->completion_remove = remove; - } - - if (msgbufcount != args->msgbufcount) { - if (put_user(msgbufcount, msgbufcountp)) - ret = -EFAULT; - } -out: - if (ret) - complete(&instance->remove_event); - mutex_unlock(&instance->completion_mutex); - DEBUG_TRACE(AWAIT_COMPLETION_LINE); - - return ret; -} - -static long -vchiq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct vchiq_instance *instance = file->private_data; - int status = 0; - struct vchiq_service *service = NULL; - long ret = 0; - int i, rc; - - dev_dbg(instance->state->dev, "arm: instance %p, cmd %s, arg %lx\n", instance, - ((_IOC_TYPE(cmd) == VCHIQ_IOC_MAGIC) && (_IOC_NR(cmd) <= VCHIQ_IOC_MAX)) ? - ioctl_names[_IOC_NR(cmd)] : "<invalid>", arg); - - switch (cmd) { - case VCHIQ_IOC_SHUTDOWN: - if (!instance->connected) - break; - - /* Remove all services */ - i = 0; - while ((service = next_service_by_instance(instance->state, - instance, &i))) { - status = vchiq_remove_service(instance, service->handle); - vchiq_service_put(service); - if (status) - break; - } - service = NULL; - - if (!status) { - /* Wake the completion thread and ask it to exit */ - instance->closing = 1; - complete(&instance->insert_event); - } - - break; - - case VCHIQ_IOC_CONNECT: - if (instance->connected) { - ret = -EINVAL; - break; - } - rc = mutex_lock_killable(&instance->state->mutex); - if (rc) { - dev_err(instance->state->dev, - "arm: vchiq: connect: could not lock mutex for state %d: %d\n", - instance->state->id, rc); - ret = -EINTR; - break; - } - status = vchiq_connect_internal(instance->state, instance); - mutex_unlock(&instance->state->mutex); - - if (!status) - instance->connected = 1; - else - dev_err(instance->state->dev, - "arm: vchiq: could not connect: %d\n", status); - break; - - case VCHIQ_IOC_CREATE_SERVICE: { - struct vchiq_create_service __user *argp; - struct vchiq_create_service args; - - argp = (void __user *)arg; - if (copy_from_user(&args, argp, sizeof(args))) { - ret = -EFAULT; - break; - } - - ret = vchiq_ioc_create_service(instance, &args); - if (ret < 0) - break; - - if (put_user(args.handle, &argp->handle)) { - vchiq_remove_service(instance, args.handle); - ret = -EFAULT; - } - } break; - - case VCHIQ_IOC_CLOSE_SERVICE: - case VCHIQ_IOC_REMOVE_SERVICE: { - unsigned int handle = (unsigned int)arg; - struct user_service *user_service; - - service = find_service_for_instance(instance, handle); - if (!service) { - ret = -EINVAL; - break; - } - - user_service = service->base.userdata; - - /* - * close_pending is false on first entry, and when the - * wait in vchiq_close_service has been interrupted. - */ - if (!user_service->close_pending) { - status = (cmd == VCHIQ_IOC_CLOSE_SERVICE) ? - vchiq_close_service(instance, service->handle) : - vchiq_remove_service(instance, service->handle); - if (status) - break; - } - - /* - * close_pending is true once the underlying service - * has been closed until the client library calls the - * CLOSE_DELIVERED ioctl, signalling close_event. - */ - if (user_service->close_pending && - wait_for_completion_interruptible(&user_service->close_event)) - status = -EAGAIN; - break; - } - - case VCHIQ_IOC_USE_SERVICE: - case VCHIQ_IOC_RELEASE_SERVICE: { - unsigned int handle = (unsigned int)arg; - - service = find_service_for_instance(instance, handle); - if (service) { - ret = (cmd == VCHIQ_IOC_USE_SERVICE) ? - vchiq_use_service_internal(service) : - vchiq_release_service_internal(service); - if (ret) { - dev_err(instance->state->dev, - "suspend: cmd %s returned error %ld for service %p4cc:%03d\n", - (cmd == VCHIQ_IOC_USE_SERVICE) ? - "VCHIQ_IOC_USE_SERVICE" : - "VCHIQ_IOC_RELEASE_SERVICE", - ret, &service->base.fourcc, - service->client_id); - } - } else { - ret = -EINVAL; - } - } break; - - case VCHIQ_IOC_QUEUE_MESSAGE: { - struct vchiq_queue_message args; - - if (copy_from_user(&args, (const void __user *)arg, - sizeof(args))) { - ret = -EFAULT; - break; - } - - service = find_service_for_instance(instance, args.handle); - - if (service && (args.count <= MAX_ELEMENTS)) { - /* Copy elements into kernel space */ - struct vchiq_element elements[MAX_ELEMENTS]; - - if (copy_from_user(elements, args.elements, - args.count * sizeof(struct vchiq_element)) == 0) - ret = vchiq_ioc_queue_message(instance, args.handle, elements, - args.count); - else - ret = -EFAULT; - } else { - ret = -EINVAL; - } - } break; - - case VCHIQ_IOC_QUEUE_BULK_TRANSMIT: - case VCHIQ_IOC_QUEUE_BULK_RECEIVE: { - struct vchiq_queue_bulk_transfer args; - struct vchiq_queue_bulk_transfer __user *argp; - - enum vchiq_bulk_dir dir = - (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT) ? - VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE; - - argp = (void __user *)arg; - if (copy_from_user(&args, argp, sizeof(args))) { - ret = -EFAULT; - break; - } - - ret = vchiq_irq_queue_bulk_tx_rx(instance, &args, - dir, &argp->mode); - } break; - - case VCHIQ_IOC_AWAIT_COMPLETION: { - struct vchiq_await_completion args; - struct vchiq_await_completion __user *argp; - - argp = (void __user *)arg; - if (copy_from_user(&args, argp, sizeof(args))) { - ret = -EFAULT; - break; - } - - ret = vchiq_ioc_await_completion(instance, &args, - &argp->msgbufcount); - } break; - - case VCHIQ_IOC_DEQUEUE_MESSAGE: { - struct vchiq_dequeue_message args; - - if (copy_from_user(&args, (const void __user *)arg, - sizeof(args))) { - ret = -EFAULT; - break; - } - - ret = vchiq_ioc_dequeue_message(instance, &args); - } break; - - case VCHIQ_IOC_GET_CLIENT_ID: { - unsigned int handle = (unsigned int)arg; - - ret = vchiq_get_client_id(instance, handle); - } break; - - case VCHIQ_IOC_GET_CONFIG: { - struct vchiq_get_config args; - struct vchiq_config config; - - if (copy_from_user(&args, (const void __user *)arg, - sizeof(args))) { - ret = -EFAULT; - break; - } - if (args.config_size > sizeof(config)) { - ret = -EINVAL; - break; - } - - vchiq_get_config(&config); - if (copy_to_user(args.pconfig, &config, args.config_size)) { - ret = -EFAULT; - break; - } - } break; - - case VCHIQ_IOC_SET_SERVICE_OPTION: { - struct vchiq_set_service_option args; - - if (copy_from_user(&args, (const void __user *)arg, - sizeof(args))) { - ret = -EFAULT; - break; - } - - service = find_service_for_instance(instance, args.handle); - if (!service) { - ret = -EINVAL; - break; - } - - ret = vchiq_set_service_option(instance, args.handle, args.option, - args.value); - } break; - - case VCHIQ_IOC_LIB_VERSION: { - unsigned int lib_version = (unsigned int)arg; - - if (lib_version < VCHIQ_VERSION_MIN) - ret = -EINVAL; - else if (lib_version >= VCHIQ_VERSION_CLOSE_DELIVERED) - instance->use_close_delivered = 1; - } break; - - case VCHIQ_IOC_CLOSE_DELIVERED: { - unsigned int handle = (unsigned int)arg; - - service = find_closed_service_for_instance(instance, handle); - if (service) { - struct user_service *user_service = - (struct user_service *)service->base.userdata; - close_delivered(user_service); - } else { - ret = -EINVAL; - } - } break; - - default: - ret = -ENOTTY; - break; - } - - if (service) - vchiq_service_put(service); - - if (ret == 0) { - if (status == -EINVAL) - ret = -EIO; - else if (status == -EAGAIN) - ret = -EINTR; - } - - if (!status && (ret < 0) && (ret != -EINTR) && (ret != -EWOULDBLOCK)) { - dev_dbg(instance->state->dev, - "arm: ioctl instance %p, cmd %s -> status %d, %ld\n", - instance, (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? - ioctl_names[_IOC_NR(cmd)] : "<invalid>", status, ret); - } else { - dev_dbg(instance->state->dev, - "arm: ioctl instance %p, cmd %s -> status %d\n, %ld\n", - instance, (_IOC_NR(cmd) <= VCHIQ_IOC_MAX) ? - ioctl_names[_IOC_NR(cmd)] : "<invalid>", status, ret); - } - - return ret; -} - -#if defined(CONFIG_COMPAT) - -struct vchiq_service_params32 { - int fourcc; - compat_uptr_t callback; - compat_uptr_t userdata; - short version; /* Increment for non-trivial changes */ - short version_min; /* Update for incompatible changes */ -}; - -struct vchiq_create_service32 { - struct vchiq_service_params32 params; - int is_open; - int is_vchi; - unsigned int handle; /* OUT */ -}; - -#define VCHIQ_IOC_CREATE_SERVICE32 \ - _IOWR(VCHIQ_IOC_MAGIC, 2, struct vchiq_create_service32) - -static long -vchiq_compat_ioctl_create_service(struct file *file, unsigned int cmd, - struct vchiq_create_service32 __user *ptrargs32) -{ - struct vchiq_create_service args; - struct vchiq_create_service32 args32; - struct vchiq_instance *instance = file->private_data; - long ret; - - if (copy_from_user(&args32, ptrargs32, sizeof(args32))) - return -EFAULT; - - args = (struct vchiq_create_service) { - .params = { - .fourcc = args32.params.fourcc, - .callback = compat_ptr(args32.params.callback), - .userdata = compat_ptr(args32.params.userdata), - .version = args32.params.version, - .version_min = args32.params.version_min, - }, - .is_open = args32.is_open, - .is_vchi = args32.is_vchi, - .handle = args32.handle, - }; - - ret = vchiq_ioc_create_service(instance, &args); - if (ret < 0) - return ret; - - if (put_user(args.handle, &ptrargs32->handle)) { - vchiq_remove_service(instance, args.handle); - return -EFAULT; - } - - return 0; -} - -struct vchiq_element32 { - compat_uptr_t data; - unsigned int size; -}; - -struct vchiq_queue_message32 { - unsigned int handle; - unsigned int count; - compat_uptr_t elements; -}; - -#define VCHIQ_IOC_QUEUE_MESSAGE32 \ - _IOW(VCHIQ_IOC_MAGIC, 4, struct vchiq_queue_message32) - -static long -vchiq_compat_ioctl_queue_message(struct file *file, - unsigned int cmd, - struct vchiq_queue_message32 __user *arg) -{ - struct vchiq_queue_message args; - struct vchiq_queue_message32 args32; - struct vchiq_service *service; - struct vchiq_instance *instance = file->private_data; - int ret; - - if (copy_from_user(&args32, arg, sizeof(args32))) - return -EFAULT; - - args = (struct vchiq_queue_message) { - .handle = args32.handle, - .count = args32.count, - .elements = compat_ptr(args32.elements), - }; - - if (args32.count > MAX_ELEMENTS) - return -EINVAL; - - service = find_service_for_instance(instance, args.handle); - if (!service) - return -EINVAL; - - if (args32.elements && args32.count) { - struct vchiq_element32 element32[MAX_ELEMENTS]; - struct vchiq_element elements[MAX_ELEMENTS]; - unsigned int count; - - if (copy_from_user(&element32, args.elements, - sizeof(element32))) { - vchiq_service_put(service); - return -EFAULT; - } - - for (count = 0; count < args32.count; count++) { - elements[count].data = - compat_ptr(element32[count].data); - elements[count].size = element32[count].size; - } - ret = vchiq_ioc_queue_message(instance, args.handle, elements, - args.count); - } else { - ret = -EINVAL; - } - vchiq_service_put(service); - - return ret; -} - -struct vchiq_queue_bulk_transfer32 { - unsigned int handle; - compat_uptr_t data; - unsigned int size; - compat_uptr_t userdata; - enum vchiq_bulk_mode mode; -}; - -#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT32 \ - _IOWR(VCHIQ_IOC_MAGIC, 5, struct vchiq_queue_bulk_transfer32) -#define VCHIQ_IOC_QUEUE_BULK_RECEIVE32 \ - _IOWR(VCHIQ_IOC_MAGIC, 6, struct vchiq_queue_bulk_transfer32) - -static long -vchiq_compat_ioctl_queue_bulk(struct file *file, - unsigned int cmd, - struct vchiq_queue_bulk_transfer32 __user *argp) -{ - struct vchiq_queue_bulk_transfer32 args32; - struct vchiq_queue_bulk_transfer args; - enum vchiq_bulk_dir dir = (cmd == VCHIQ_IOC_QUEUE_BULK_TRANSMIT32) ? - VCHIQ_BULK_TRANSMIT : VCHIQ_BULK_RECEIVE; - - if (copy_from_user(&args32, argp, sizeof(args32))) - return -EFAULT; - - args = (struct vchiq_queue_bulk_transfer) { - .handle = args32.handle, - .data = compat_ptr(args32.data), - .size = args32.size, - .userdata = compat_ptr(args32.userdata), - .mode = args32.mode, - }; - - return vchiq_irq_queue_bulk_tx_rx(file->private_data, &args, - dir, &argp->mode); -} - -struct vchiq_await_completion32 { - unsigned int count; - compat_uptr_t buf; - unsigned int msgbufsize; - unsigned int msgbufcount; /* IN/OUT */ - compat_uptr_t msgbufs; -}; - -#define VCHIQ_IOC_AWAIT_COMPLETION32 \ - _IOWR(VCHIQ_IOC_MAGIC, 7, struct vchiq_await_completion32) - -static long -vchiq_compat_ioctl_await_completion(struct file *file, - unsigned int cmd, - struct vchiq_await_completion32 __user *argp) -{ - struct vchiq_await_completion args; - struct vchiq_await_completion32 args32; - - if (copy_from_user(&args32, argp, sizeof(args32))) - return -EFAULT; - - args = (struct vchiq_await_completion) { - .count = args32.count, - .buf = compat_ptr(args32.buf), - .msgbufsize = args32.msgbufsize, - .msgbufcount = args32.msgbufcount, - .msgbufs = compat_ptr(args32.msgbufs), - }; - - return vchiq_ioc_await_completion(file->private_data, &args, - &argp->msgbufcount); -} - -struct vchiq_dequeue_message32 { - unsigned int handle; - int blocking; - unsigned int bufsize; - compat_uptr_t buf; -}; - -#define VCHIQ_IOC_DEQUEUE_MESSAGE32 \ - _IOWR(VCHIQ_IOC_MAGIC, 8, struct vchiq_dequeue_message32) - -static long -vchiq_compat_ioctl_dequeue_message(struct file *file, - unsigned int cmd, - struct vchiq_dequeue_message32 __user *arg) -{ - struct vchiq_dequeue_message32 args32; - struct vchiq_dequeue_message args; - - if (copy_from_user(&args32, arg, sizeof(args32))) - return -EFAULT; - - args = (struct vchiq_dequeue_message) { - .handle = args32.handle, - .blocking = args32.blocking, - .bufsize = args32.bufsize, - .buf = compat_ptr(args32.buf), - }; - - return vchiq_ioc_dequeue_message(file->private_data, &args); -} - -struct vchiq_get_config32 { - unsigned int config_size; - compat_uptr_t pconfig; -}; - -#define VCHIQ_IOC_GET_CONFIG32 \ - _IOWR(VCHIQ_IOC_MAGIC, 10, struct vchiq_get_config32) - -static long -vchiq_compat_ioctl_get_config(struct file *file, - unsigned int cmd, - struct vchiq_get_config32 __user *arg) -{ - struct vchiq_get_config32 args32; - struct vchiq_config config; - void __user *ptr; - - if (copy_from_user(&args32, arg, sizeof(args32))) - return -EFAULT; - if (args32.config_size > sizeof(config)) - return -EINVAL; - - vchiq_get_config(&config); - ptr = compat_ptr(args32.pconfig); - if (copy_to_user(ptr, &config, args32.config_size)) - return -EFAULT; - - return 0; -} - -static long -vchiq_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - void __user *argp = compat_ptr(arg); - - switch (cmd) { - case VCHIQ_IOC_CREATE_SERVICE32: - return vchiq_compat_ioctl_create_service(file, cmd, argp); - case VCHIQ_IOC_QUEUE_MESSAGE32: - return vchiq_compat_ioctl_queue_message(file, cmd, argp); - case VCHIQ_IOC_QUEUE_BULK_TRANSMIT32: - case VCHIQ_IOC_QUEUE_BULK_RECEIVE32: - return vchiq_compat_ioctl_queue_bulk(file, cmd, argp); - case VCHIQ_IOC_AWAIT_COMPLETION32: - return vchiq_compat_ioctl_await_completion(file, cmd, argp); - case VCHIQ_IOC_DEQUEUE_MESSAGE32: - return vchiq_compat_ioctl_dequeue_message(file, cmd, argp); - case VCHIQ_IOC_GET_CONFIG32: - return vchiq_compat_ioctl_get_config(file, cmd, argp); - default: - return vchiq_ioctl(file, cmd, (unsigned long)argp); - } -} - -#endif - -static int vchiq_open(struct inode *inode, struct file *file) -{ - struct miscdevice *vchiq_miscdev = file->private_data; - struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(vchiq_miscdev->parent); - struct vchiq_state *state = &mgmt->state; - struct vchiq_instance *instance; - - dev_dbg(state->dev, "arm: vchiq open\n"); - - if (!vchiq_remote_initialised(state)) { - dev_dbg(state->dev, "arm: vchiq has no connection to VideoCore\n"); - return -ENOTCONN; - } - - instance = kzalloc(sizeof(*instance), GFP_KERNEL); - if (!instance) - return -ENOMEM; - - instance->state = state; - instance->pid = current->tgid; - - vchiq_debugfs_add_instance(instance); - - init_completion(&instance->insert_event); - init_completion(&instance->remove_event); - mutex_init(&instance->completion_mutex); - mutex_init(&instance->bulk_waiter_list_mutex); - INIT_LIST_HEAD(&instance->bulk_waiter_list); - - file->private_data = instance; - - return 0; -} - -static int vchiq_release(struct inode *inode, struct file *file) -{ - struct vchiq_instance *instance = file->private_data; - struct vchiq_state *state = instance->state; - struct vchiq_service *service; - int ret = 0; - int i; - - dev_dbg(state->dev, "arm: instance=%p\n", instance); - - if (!vchiq_remote_initialised(state)) { - ret = -EPERM; - goto out; - } - - /* Ensure videocore is awake to allow termination. */ - vchiq_use_internal(instance->state, NULL, USE_TYPE_VCHIQ); - - mutex_lock(&instance->completion_mutex); - - /* Wake the completion thread and ask it to exit */ - instance->closing = 1; - complete(&instance->insert_event); - - mutex_unlock(&instance->completion_mutex); - - /* Wake the slot handler if the completion queue is full. */ - complete(&instance->remove_event); - - /* Mark all services for termination... */ - i = 0; - while ((service = next_service_by_instance(state, instance, &i))) { - struct user_service *user_service = service->base.userdata; - - /* Wake the slot handler if the msg queue is full. */ - complete(&user_service->remove_event); - - vchiq_terminate_service_internal(service); - vchiq_service_put(service); - } - - /* ...and wait for them to die */ - i = 0; - while ((service = next_service_by_instance(state, instance, &i))) { - struct user_service *user_service = service->base.userdata; - - wait_for_completion(&service->remove_event); - - if (WARN_ON(service->srvstate != VCHIQ_SRVSTATE_FREE)) { - vchiq_service_put(service); - break; - } - - spin_lock(&service->state->msg_queue_spinlock); - - while (user_service->msg_remove != user_service->msg_insert) { - struct vchiq_header *header; - int m = user_service->msg_remove & (MSG_QUEUE_SIZE - 1); - - header = user_service->msg_queue[m]; - user_service->msg_remove++; - spin_unlock(&service->state->msg_queue_spinlock); - - if (header) - vchiq_release_message(instance, service->handle, header); - spin_lock(&service->state->msg_queue_spinlock); - } - - spin_unlock(&service->state->msg_queue_spinlock); - - vchiq_service_put(service); - } - - /* Release any closed services */ - while (instance->completion_remove != instance->completion_insert) { - struct vchiq_completion_data_kernel *completion; - struct vchiq_service *service; - - completion = &instance->completions[instance->completion_remove - & (MAX_COMPLETIONS - 1)]; - service = completion->service_userdata; - if (completion->reason == VCHIQ_SERVICE_CLOSED) { - struct user_service *user_service = - service->base.userdata; - - /* Wake any blocked user-thread */ - if (instance->use_close_delivered) - complete(&user_service->close_event); - vchiq_service_put(service); - } - instance->completion_remove++; - } - - /* Release the PEER service count. */ - vchiq_release_internal(instance->state, NULL); - - free_bulk_waiter(instance); - - vchiq_debugfs_remove_instance(instance); - - kfree(instance); - file->private_data = NULL; - -out: - return ret; -} - -static const struct file_operations -vchiq_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = vchiq_ioctl, -#if defined(CONFIG_COMPAT) - .compat_ioctl = vchiq_compat_ioctl, -#endif - .open = vchiq_open, - .release = vchiq_release, -}; - -static struct miscdevice vchiq_miscdev = { - .fops = &vchiq_fops, - .minor = MISC_DYNAMIC_MINOR, - .name = "vchiq", - -}; - -/** - * vchiq_register_chrdev - Register the char driver for vchiq - * and create the necessary class and - * device files in userspace. - * @parent: The parent of the char device. - * - * Returns 0 on success else returns the error code. - */ -int vchiq_register_chrdev(struct device *parent) -{ - vchiq_miscdev.parent = parent; - - return misc_register(&vchiq_miscdev); -} - -/** - * vchiq_deregister_chrdev - Deregister and cleanup the vchiq char - * driver and device files - */ -void vchiq_deregister_chrdev(void) -{ - misc_deregister(&vchiq_miscdev); -} diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h deleted file mode 100644 index afb71a83cfe7..000000000000 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h +++ /dev/null @@ -1,113 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ -/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */ - -#ifndef VCHIQ_IOCTLS_H -#define VCHIQ_IOCTLS_H - -#include <linux/ioctl.h> - -#include "../../include/linux/raspberrypi/vchiq.h" - -#define VCHIQ_IOC_MAGIC 0xc4 -#define VCHIQ_INVALID_HANDLE (~0) - -struct vchiq_service_params { - int fourcc; - int __user (*callback)(enum vchiq_reason reason, - struct vchiq_header *header, - unsigned int handle, - void *bulk_userdata); - void __user *userdata; - short version; /* Increment for non-trivial changes */ - short version_min; /* Update for incompatible changes */ -}; - -struct vchiq_create_service { - struct vchiq_service_params params; - int is_open; - int is_vchi; - unsigned int handle; /* OUT */ -}; - -struct vchiq_queue_message { - unsigned int handle; - unsigned int count; - const struct vchiq_element __user *elements; -}; - -struct vchiq_queue_bulk_transfer { - unsigned int handle; - void __user *data; - unsigned int size; - void __user *userdata; - enum vchiq_bulk_mode mode; -}; - -struct vchiq_completion_data { - enum vchiq_reason reason; - struct vchiq_header __user *header; - void __user *service_userdata; - void __user *cb_userdata; -}; - -struct vchiq_await_completion { - unsigned int count; - struct vchiq_completion_data __user *buf; - unsigned int msgbufsize; - unsigned int msgbufcount; /* IN/OUT */ - void * __user *msgbufs; -}; - -struct vchiq_dequeue_message { - unsigned int handle; - int blocking; - unsigned int bufsize; - void __user *buf; -}; - -struct vchiq_get_config { - unsigned int config_size; - struct vchiq_config __user *pconfig; -}; - -struct vchiq_set_service_option { - unsigned int handle; - enum vchiq_service_option option; - int value; -}; - -struct vchiq_dump_mem { - void __user *virt_addr; - size_t num_bytes; -}; - -#define VCHIQ_IOC_CONNECT _IO(VCHIQ_IOC_MAGIC, 0) -#define VCHIQ_IOC_SHUTDOWN _IO(VCHIQ_IOC_MAGIC, 1) -#define VCHIQ_IOC_CREATE_SERVICE \ - _IOWR(VCHIQ_IOC_MAGIC, 2, struct vchiq_create_service) -#define VCHIQ_IOC_REMOVE_SERVICE _IO(VCHIQ_IOC_MAGIC, 3) -#define VCHIQ_IOC_QUEUE_MESSAGE \ - _IOW(VCHIQ_IOC_MAGIC, 4, struct vchiq_queue_message) -#define VCHIQ_IOC_QUEUE_BULK_TRANSMIT \ - _IOWR(VCHIQ_IOC_MAGIC, 5, struct vchiq_queue_bulk_transfer) -#define VCHIQ_IOC_QUEUE_BULK_RECEIVE \ - _IOWR(VCHIQ_IOC_MAGIC, 6, struct vchiq_queue_bulk_transfer) -#define VCHIQ_IOC_AWAIT_COMPLETION \ - _IOWR(VCHIQ_IOC_MAGIC, 7, struct vchiq_await_completion) -#define VCHIQ_IOC_DEQUEUE_MESSAGE \ - _IOWR(VCHIQ_IOC_MAGIC, 8, struct vchiq_dequeue_message) -#define VCHIQ_IOC_GET_CLIENT_ID _IO(VCHIQ_IOC_MAGIC, 9) -#define VCHIQ_IOC_GET_CONFIG \ - _IOWR(VCHIQ_IOC_MAGIC, 10, struct vchiq_get_config) -#define VCHIQ_IOC_CLOSE_SERVICE _IO(VCHIQ_IOC_MAGIC, 11) -#define VCHIQ_IOC_USE_SERVICE _IO(VCHIQ_IOC_MAGIC, 12) -#define VCHIQ_IOC_RELEASE_SERVICE _IO(VCHIQ_IOC_MAGIC, 13) -#define VCHIQ_IOC_SET_SERVICE_OPTION \ - _IOW(VCHIQ_IOC_MAGIC, 14, struct vchiq_set_service_option) -#define VCHIQ_IOC_DUMP_PHYS_MEM \ - _IOW(VCHIQ_IOC_MAGIC, 15, struct vchiq_dump_mem) -#define VCHIQ_IOC_LIB_VERSION _IO(VCHIQ_IOC_MAGIC, 16) -#define VCHIQ_IOC_CLOSE_DELIVERED _IO(VCHIQ_IOC_MAGIC, 17) -#define VCHIQ_IOC_MAX 17 - -#endif diff --git a/drivers/staging/vc04_services/vchiq-mmal/Kconfig b/drivers/staging/vc04_services/vchiq-mmal/Kconfig deleted file mode 100644 index c99525a0bb45..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -config BCM2835_VCHIQ_MMAL - tristate "BCM2835 MMAL VCHIQ service" - depends on BCM2835_VCHIQ - help - Enables the MMAL API over VCHIQ interface as used for the - majority of the multimedia services on VideoCore. - Defaults to Y when the Broadcomd BCM2835 camera host is selected. diff --git a/drivers/staging/vc04_services/vchiq-mmal/Makefile b/drivers/staging/vc04_services/vchiq-mmal/Makefile deleted file mode 100644 index 6937f6534c26..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -bcm2835-mmal-vchiq-objs := mmal-vchiq.o - -obj-$(CONFIG_BCM2835_VCHIQ_MMAL) += bcm2835-mmal-vchiq.o diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h deleted file mode 100644 index b33129403a30..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-common.h +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 V4L2 driver - * - * Copyright © 2013 Raspberry Pi (Trading) Ltd. - * - * Authors: Vincent Sanders @ Collabora - * Dave Stevenson @ Broadcom - * (now dave.stevenson@raspberrypi.org) - * Simon Mellor @ Broadcom - * Luke Diamand @ Broadcom - * - * MMAL structures - * - */ -#ifndef MMAL_COMMON_H -#define MMAL_COMMON_H - -#define MMAL_FOURCC(a, b, c, d) ((a) | (b << 8) | (c << 16) | (d << 24)) -#define MMAL_MAGIC MMAL_FOURCC('m', 'm', 'a', 'l') - -/** Special value signalling that time is not known */ -#define MMAL_TIME_UNKNOWN BIT_ULL(63) - -struct mmal_msg_context; - -/* mapping between v4l and mmal video modes */ -struct mmal_fmt { - u32 fourcc; /* v4l2 format id */ - int flags; /* v4l2 flags field */ - u32 mmal; - int depth; - u32 mmal_component; /* MMAL component index to be used to encode */ - u32 ybbp; /* depth of first Y plane for planar formats */ - bool remove_padding; /* Does the GPU have to remove padding, - * or can we do hide padding via bytesperline. - */ -}; - -/* buffer for one video frame */ -struct mmal_buffer { - /* v4l buffer data -- must be first */ - struct vb2_v4l2_buffer vb; - - /* list of buffers available */ - struct list_head list; - - void *buffer; /* buffer pointer */ - unsigned long buffer_size; /* size of allocated buffer */ - - struct mmal_msg_context *msg_context; - - unsigned long length; - u32 mmal_flags; - s64 dts; - s64 pts; -}; - -/* */ -struct mmal_colourfx { - s32 enable; - u32 u; - u32 v; -}; -#endif diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h deleted file mode 100644 index e15ae7b24f73..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-encodings.h +++ /dev/null @@ -1,124 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 V4L2 driver - * - * Copyright © 2013 Raspberry Pi (Trading) Ltd. - * - * Authors: Vincent Sanders @ Collabora - * Dave Stevenson @ Broadcom - * (now dave.stevenson@raspberrypi.org) - * Simon Mellor @ Broadcom - * Luke Diamand @ Broadcom - */ -#ifndef MMAL_ENCODINGS_H -#define MMAL_ENCODINGS_H - -#define MMAL_ENCODING_H264 MMAL_FOURCC('H', '2', '6', '4') -#define MMAL_ENCODING_H263 MMAL_FOURCC('H', '2', '6', '3') -#define MMAL_ENCODING_MP4V MMAL_FOURCC('M', 'P', '4', 'V') -#define MMAL_ENCODING_MP2V MMAL_FOURCC('M', 'P', '2', 'V') -#define MMAL_ENCODING_MP1V MMAL_FOURCC('M', 'P', '1', 'V') -#define MMAL_ENCODING_WMV3 MMAL_FOURCC('W', 'M', 'V', '3') -#define MMAL_ENCODING_WMV2 MMAL_FOURCC('W', 'M', 'V', '2') -#define MMAL_ENCODING_WMV1 MMAL_FOURCC('W', 'M', 'V', '1') -#define MMAL_ENCODING_WVC1 MMAL_FOURCC('W', 'V', 'C', '1') -#define MMAL_ENCODING_VP8 MMAL_FOURCC('V', 'P', '8', ' ') -#define MMAL_ENCODING_VP7 MMAL_FOURCC('V', 'P', '7', ' ') -#define MMAL_ENCODING_VP6 MMAL_FOURCC('V', 'P', '6', ' ') -#define MMAL_ENCODING_THEORA MMAL_FOURCC('T', 'H', 'E', 'O') -#define MMAL_ENCODING_SPARK MMAL_FOURCC('S', 'P', 'R', 'K') -#define MMAL_ENCODING_MJPEG MMAL_FOURCC('M', 'J', 'P', 'G') - -#define MMAL_ENCODING_JPEG MMAL_FOURCC('J', 'P', 'E', 'G') -#define MMAL_ENCODING_GIF MMAL_FOURCC('G', 'I', 'F', ' ') -#define MMAL_ENCODING_PNG MMAL_FOURCC('P', 'N', 'G', ' ') -#define MMAL_ENCODING_PPM MMAL_FOURCC('P', 'P', 'M', ' ') -#define MMAL_ENCODING_TGA MMAL_FOURCC('T', 'G', 'A', ' ') -#define MMAL_ENCODING_BMP MMAL_FOURCC('B', 'M', 'P', ' ') - -#define MMAL_ENCODING_I420 MMAL_FOURCC('I', '4', '2', '0') -#define MMAL_ENCODING_I420_SLICE MMAL_FOURCC('S', '4', '2', '0') -#define MMAL_ENCODING_YV12 MMAL_FOURCC('Y', 'V', '1', '2') -#define MMAL_ENCODING_I422 MMAL_FOURCC('I', '4', '2', '2') -#define MMAL_ENCODING_I422_SLICE MMAL_FOURCC('S', '4', '2', '2') -#define MMAL_ENCODING_YUYV MMAL_FOURCC('Y', 'U', 'Y', 'V') -#define MMAL_ENCODING_YVYU MMAL_FOURCC('Y', 'V', 'Y', 'U') -#define MMAL_ENCODING_UYVY MMAL_FOURCC('U', 'Y', 'V', 'Y') -#define MMAL_ENCODING_VYUY MMAL_FOURCC('V', 'Y', 'U', 'Y') -#define MMAL_ENCODING_NV12 MMAL_FOURCC('N', 'V', '1', '2') -#define MMAL_ENCODING_NV21 MMAL_FOURCC('N', 'V', '2', '1') -#define MMAL_ENCODING_ARGB MMAL_FOURCC('A', 'R', 'G', 'B') -#define MMAL_ENCODING_RGBA MMAL_FOURCC('R', 'G', 'B', 'A') -#define MMAL_ENCODING_ABGR MMAL_FOURCC('A', 'B', 'G', 'R') -#define MMAL_ENCODING_BGRA MMAL_FOURCC('B', 'G', 'R', 'A') -#define MMAL_ENCODING_RGB16 MMAL_FOURCC('R', 'G', 'B', '2') -#define MMAL_ENCODING_RGB24 MMAL_FOURCC('R', 'G', 'B', '3') -#define MMAL_ENCODING_RGB32 MMAL_FOURCC('R', 'G', 'B', '4') -#define MMAL_ENCODING_BGR16 MMAL_FOURCC('B', 'G', 'R', '2') -#define MMAL_ENCODING_BGR24 MMAL_FOURCC('B', 'G', 'R', '3') -#define MMAL_ENCODING_BGR32 MMAL_FOURCC('B', 'G', 'R', '4') - -/** SAND Video (YUVUV128) format, native format understood by VideoCore. - * This format is *not* opaque - if requested you will receive full frames - * of YUV_UV video. - */ -#define MMAL_ENCODING_YUVUV128 MMAL_FOURCC('S', 'A', 'N', 'D') - -/** VideoCore opaque image format, image handles are returned to - * the host but not the actual image data. - */ -#define MMAL_ENCODING_OPAQUE MMAL_FOURCC('O', 'P', 'Q', 'V') - -/** An EGL image handle - */ -#define MMAL_ENCODING_EGL_IMAGE MMAL_FOURCC('E', 'G', 'L', 'I') - -/* }@ */ - -/** \name Pre-defined audio encodings */ -/* @{ */ -#define MMAL_ENCODING_PCM_UNSIGNED_BE MMAL_FOURCC('P', 'C', 'M', 'U') -#define MMAL_ENCODING_PCM_UNSIGNED_LE MMAL_FOURCC('p', 'c', 'm', 'u') -#define MMAL_ENCODING_PCM_SIGNED_BE MMAL_FOURCC('P', 'C', 'M', 'S') -#define MMAL_ENCODING_PCM_SIGNED_LE MMAL_FOURCC('p', 'c', 'm', 's') -#define MMAL_ENCODING_PCM_FLOAT_BE MMAL_FOURCC('P', 'C', 'M', 'F') -#define MMAL_ENCODING_PCM_FLOAT_LE MMAL_FOURCC('p', 'c', 'm', 'f') - -/* Pre-defined H264 encoding variants */ - -/** ISO 14496-10 Annex B byte stream format */ -#define MMAL_ENCODING_VARIANT_H264_DEFAULT 0 -/** ISO 14496-15 AVC stream format */ -#define MMAL_ENCODING_VARIANT_H264_AVC1 MMAL_FOURCC('A', 'V', 'C', '1') -/** Implicitly delineated NAL units without emulation prevention */ -#define MMAL_ENCODING_VARIANT_H264_RAW MMAL_FOURCC('R', 'A', 'W', ' ') - -/** \defgroup MmalColorSpace List of pre-defined video color spaces - * This defines a list of common color spaces. This list isn't exhaustive and - * is only provided as a convenience to avoid clients having to use FourCC - * codes directly. However components are allowed to define and use their own - * FourCC codes. - */ -/* @{ */ - -/** Unknown color space */ -#define MMAL_COLOR_SPACE_UNKNOWN 0 -/** ITU-R BT.601-5 [SDTV] */ -#define MMAL_COLOR_SPACE_ITUR_BT601 MMAL_FOURCC('Y', '6', '0', '1') -/** ITU-R BT.709-3 [HDTV] */ -#define MMAL_COLOR_SPACE_ITUR_BT709 MMAL_FOURCC('Y', '7', '0', '9') -/** JPEG JFIF */ -#define MMAL_COLOR_SPACE_JPEG_JFIF MMAL_FOURCC('Y', 'J', 'F', 'I') -/** Title 47 Code of Federal Regulations (2003) 73.682 (a) (20) */ -#define MMAL_COLOR_SPACE_FCC MMAL_FOURCC('Y', 'F', 'C', 'C') -/** Society of Motion Picture and Television Engineers 240M (1999) */ -#define MMAL_COLOR_SPACE_SMPTE240M MMAL_FOURCC('Y', '2', '4', '0') -/** ITU-R BT.470-2 System M */ -#define MMAL_COLOR_SPACE_BT470_2_M MMAL_FOURCC('Y', '_', '_', 'M') -/** ITU-R BT.470-2 System BG */ -#define MMAL_COLOR_SPACE_BT470_2_BG MMAL_FOURCC('Y', '_', 'B', 'G') -/** JPEG JFIF, but with 16..255 luma */ -#define MMAL_COLOR_SPACE_JFIF_Y16_255 MMAL_FOURCC('Y', 'Y', '1', '6') -/* @} MmalColorSpace List */ - -#endif /* MMAL_ENCODINGS_H */ diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h deleted file mode 100644 index 492d4c5dca08..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-common.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 V4L2 driver - * - * Copyright © 2013 Raspberry Pi (Trading) Ltd. - * - * Authors: Vincent Sanders @ Collabora - * Dave Stevenson @ Broadcom - * (now dave.stevenson@raspberrypi.org) - * Simon Mellor @ Broadcom - * Luke Diamand @ Broadcom - */ - -#ifndef MMAL_MSG_COMMON_H -#define MMAL_MSG_COMMON_H - -#include <linux/types.h> - -enum mmal_msg_status { - MMAL_MSG_STATUS_SUCCESS = 0, /**< Success */ - MMAL_MSG_STATUS_ENOMEM, /**< Out of memory */ - MMAL_MSG_STATUS_ENOSPC, /**< Out of resources other than memory */ - MMAL_MSG_STATUS_EINVAL, /**< Argument is invalid */ - MMAL_MSG_STATUS_ENOSYS, /**< Function not implemented */ - MMAL_MSG_STATUS_ENOENT, /**< No such file or directory */ - MMAL_MSG_STATUS_ENXIO, /**< No such device or address */ - MMAL_MSG_STATUS_EIO, /**< I/O error */ - MMAL_MSG_STATUS_ESPIPE, /**< Illegal seek */ - MMAL_MSG_STATUS_ECORRUPT, /**< Data is corrupt \attention */ - MMAL_MSG_STATUS_ENOTREADY, /**< Component is not ready */ - MMAL_MSG_STATUS_ECONFIG, /**< Component is not configured */ - MMAL_MSG_STATUS_EISCONN, /**< Port is already connected */ - MMAL_MSG_STATUS_ENOTCONN, /**< Port is disconnected */ - MMAL_MSG_STATUS_EAGAIN, /**< Resource temporarily unavailable. */ - MMAL_MSG_STATUS_EFAULT, /**< Bad address */ -}; - -struct mmal_rect { - s32 x; /**< x coordinate (from left) */ - s32 y; /**< y coordinate (from top) */ - s32 width; /**< width */ - s32 height; /**< height */ -}; - -#endif /* MMAL_MSG_COMMON_H */ diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h deleted file mode 100644 index 5569876d8c7d..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-format.h +++ /dev/null @@ -1,108 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 V4L2 driver - * - * Copyright © 2013 Raspberry Pi (Trading) Ltd. - * - * Authors: Vincent Sanders @ Collabora - * Dave Stevenson @ Broadcom - * (now dave.stevenson@raspberrypi.org) - * Simon Mellor @ Broadcom - * Luke Diamand @ Broadcom - */ - -#ifndef MMAL_MSG_FORMAT_H -#define MMAL_MSG_FORMAT_H - -#include <linux/math.h> - -#include "mmal-msg-common.h" - -/* MMAL_ES_FORMAT_T */ - -struct mmal_audio_format { - u32 channels; /* Number of audio channels */ - u32 sample_rate; /* Sample rate */ - - u32 bits_per_sample; /* Bits per sample */ - u32 block_align; /* Size of a block of data */ -}; - -struct mmal_video_format { - u32 width; /* Width of frame in pixels */ - u32 height; /* Height of frame in rows of pixels */ - struct mmal_rect crop; /* Visible region of the frame */ - struct s32_fract frame_rate; /* Frame rate */ - struct s32_fract par; /* Pixel aspect ratio */ - - /* - * FourCC specifying the color space of the video stream. See the - * MmalColorSpace "pre-defined color spaces" for some examples. - */ - u32 color_space; -}; - -struct mmal_subpicture_format { - u32 x_offset; - u32 y_offset; -}; - -union mmal_es_specific_format { - struct mmal_audio_format audio; - struct mmal_video_format video; - struct mmal_subpicture_format subpicture; -}; - -/* Definition of an elementary stream format (MMAL_ES_FORMAT_T) */ -struct mmal_es_format_local { - u32 type; /* enum mmal_es_type */ - - u32 encoding; /* FourCC specifying encoding of the elementary - * stream. - */ - u32 encoding_variant; /* FourCC specifying the specific - * encoding variant of the elementary - * stream. - */ - - union mmal_es_specific_format *es; /* Type specific - * information for the - * elementary stream - */ - - u32 bitrate; /* Bitrate in bits per second */ - u32 flags; /* Flags describing properties of the elementary - * stream. - */ - - u32 extradata_size; /* Size of the codec specific data */ - u8 *extradata; /* Codec specific data */ -}; - -/* Remote definition of an elementary stream format (MMAL_ES_FORMAT_T) */ -struct mmal_es_format { - u32 type; /* enum mmal_es_type */ - - u32 encoding; /* FourCC specifying encoding of the elementary - * stream. - */ - u32 encoding_variant; /* FourCC specifying the specific - * encoding variant of the elementary - * stream. - */ - - u32 es; /* Type specific - * information for the - * elementary stream - */ - - u32 bitrate; /* Bitrate in bits per second */ - u32 flags; /* Flags describing properties of the elementary - * stream. - */ - - u32 extradata_size; /* Size of the codec specific data */ - u32 extradata; /* Codec specific data */ -}; - -#endif /* MMAL_MSG_FORMAT_H */ diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h deleted file mode 100644 index 6ee4c1ed7f19..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg-port.h +++ /dev/null @@ -1,109 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 V4L2 driver - * - * Copyright © 2013 Raspberry Pi (Trading) Ltd. - * - * Authors: Vincent Sanders @ Collabora - * Dave Stevenson @ Broadcom - * (now dave.stevenson@raspberrypi.org) - * Simon Mellor @ Broadcom - * Luke Diamand @ Broadcom - */ - -/* MMAL_PORT_TYPE_T */ -enum mmal_port_type { - MMAL_PORT_TYPE_UNKNOWN = 0, /* Unknown port type */ - MMAL_PORT_TYPE_CONTROL, /* Control port */ - MMAL_PORT_TYPE_INPUT, /* Input port */ - MMAL_PORT_TYPE_OUTPUT, /* Output port */ - MMAL_PORT_TYPE_CLOCK, /* Clock port */ -}; - -/* The port is pass-through and doesn't need buffer headers allocated */ -#define MMAL_PORT_CAPABILITY_PASSTHROUGH 0x01 -/* - *The port wants to allocate the buffer payloads. - * This signals a preference that payload allocation should be done - * on this port for efficiency reasons. - */ -#define MMAL_PORT_CAPABILITY_ALLOCATION 0x02 -/* - * The port supports format change events. - * This applies to input ports and is used to let the client know - * whether the port supports being reconfigured via a format - * change event (i.e. without having to disable the port). - */ -#define MMAL_PORT_CAPABILITY_SUPPORTS_EVENT_FORMAT_CHANGE 0x04 - -/* - * mmal port structure (MMAL_PORT_T) - * - * most elements are informational only, the pointer values for - * interogation messages are generally provided as additional - * structures within the message. When used to set values only the - * buffer_num, buffer_size and userdata parameters are writable. - */ -struct mmal_port { - u32 priv; /* Private member used by the framework */ - u32 name; /* Port name. Used for debugging purposes (RO) */ - - u32 type; /* Type of the port (RO) enum mmal_port_type */ - u16 index; /* Index of the port in its type list (RO) */ - u16 index_all; /* Index of the port in the list of all ports (RO) */ - - u32 is_enabled; /* Indicates whether the port is enabled or not (RO) */ - u32 format; /* Format of the elementary stream */ - - u32 buffer_num_min; /* Minimum number of buffers the port - * requires (RO). This is set by the - * component. - */ - - u32 buffer_size_min; /* Minimum size of buffers the port - * requires (RO). This is set by the - * component. - */ - - u32 buffer_alignment_min;/* Minimum alignment requirement for - * the buffers (RO). A value of - * zero means no special alignment - * requirements. This is set by the - * component. - */ - - u32 buffer_num_recommended; /* Number of buffers the port - * recommends for optimal - * performance (RO). A value of - * zero means no special - * recommendation. This is set - * by the component. - */ - - u32 buffer_size_recommended; /* Size of buffers the port - * recommends for optimal - * performance (RO). A value of - * zero means no special - * recommendation. This is set - * by the component. - */ - - u32 buffer_num; /* Actual number of buffers the port will use. - * This is set by the client. - */ - - u32 buffer_size; /* Actual maximum size of the buffers that - * will be sent to the port. This is set by - * the client. - */ - - u32 component; /* Component this port belongs to (Read Only) */ - - u32 userdata; /* Field reserved for use by the client */ - - u32 capabilities; /* Flags describing the capabilities of a - * port (RO). Bitwise combination of \ref - * portcapabilities "Port capabilities" - * values. - */ -}; diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h deleted file mode 100644 index 1889494425eb..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-msg.h +++ /dev/null @@ -1,406 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 V4L2 driver - * - * Copyright © 2013 Raspberry Pi (Trading) Ltd. - * - * Authors: Vincent Sanders @ Collabora - * Dave Stevenson @ Broadcom - * (now dave.stevenson@raspberrypi.org) - * Simon Mellor @ Broadcom - * Luke Diamand @ Broadcom - */ - -/* - * all the data structures which serialise the MMAL protocol. note - * these are directly mapped onto the received message data. - * - * BEWARE: They seem to *assume* pointers are u32 and that there is no - * structure padding! - * - * NOTE: this implementation uses kernel types to ensure sizes. Rather - * than assigning values to enums to force their size the - * implementation uses fixed size types and not the enums (though the - * comments have the actual enum type - */ -#ifndef MMAL_MSG_H -#define MMAL_MSG_H - -#define VC_MMAL_VER 15 -#define VC_MMAL_MIN_VER 10 - -/* max total message size is 512 bytes */ -#define MMAL_MSG_MAX_SIZE 512 -/* with six 32bit header elements max payload is therefore 488 bytes */ -#define MMAL_MSG_MAX_PAYLOAD 488 - -#include "mmal-msg-common.h" -#include "mmal-msg-format.h" -#include "mmal-msg-port.h" -#include "mmal-vchiq.h" - -enum mmal_msg_type { - MMAL_MSG_TYPE_QUIT = 1, - MMAL_MSG_TYPE_SERVICE_CLOSED, - MMAL_MSG_TYPE_GET_VERSION, - MMAL_MSG_TYPE_COMPONENT_CREATE, - MMAL_MSG_TYPE_COMPONENT_DESTROY, /* 5 */ - MMAL_MSG_TYPE_COMPONENT_ENABLE, - MMAL_MSG_TYPE_COMPONENT_DISABLE, - MMAL_MSG_TYPE_PORT_INFO_GET, - MMAL_MSG_TYPE_PORT_INFO_SET, - MMAL_MSG_TYPE_PORT_ACTION, /* 10 */ - MMAL_MSG_TYPE_BUFFER_FROM_HOST, - MMAL_MSG_TYPE_BUFFER_TO_HOST, - MMAL_MSG_TYPE_GET_STATS, - MMAL_MSG_TYPE_PORT_PARAMETER_SET, - MMAL_MSG_TYPE_PORT_PARAMETER_GET, /* 15 */ - MMAL_MSG_TYPE_EVENT_TO_HOST, - MMAL_MSG_TYPE_GET_CORE_STATS_FOR_PORT, - MMAL_MSG_TYPE_OPAQUE_ALLOCATOR, - MMAL_MSG_TYPE_CONSUME_MEM, - MMAL_MSG_TYPE_LMK, /* 20 */ - MMAL_MSG_TYPE_OPAQUE_ALLOCATOR_DESC, - MMAL_MSG_TYPE_DRM_GET_LHS32, - MMAL_MSG_TYPE_DRM_GET_TIME, - MMAL_MSG_TYPE_BUFFER_FROM_HOST_ZEROLEN, - MMAL_MSG_TYPE_PORT_FLUSH, /* 25 */ - MMAL_MSG_TYPE_HOST_LOG, - MMAL_MSG_TYPE_MSG_LAST -}; - -/* port action request messages differ depending on the action type */ -enum mmal_msg_port_action_type { - MMAL_MSG_PORT_ACTION_TYPE_UNKNOWN = 0, /* Unknown action */ - MMAL_MSG_PORT_ACTION_TYPE_ENABLE, /* Enable a port */ - MMAL_MSG_PORT_ACTION_TYPE_DISABLE, /* Disable a port */ - MMAL_MSG_PORT_ACTION_TYPE_FLUSH, /* Flush a port */ - MMAL_MSG_PORT_ACTION_TYPE_CONNECT, /* Connect ports */ - MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT, /* Disconnect ports */ - MMAL_MSG_PORT_ACTION_TYPE_SET_REQUIREMENTS, /* Set buffer requirements*/ -}; - -struct mmal_msg_header { - u32 magic; - u32 type; /* enum mmal_msg_type */ - - /* Opaque handle to the control service */ - u32 control_service; - - u32 context; /* a u32 per message context */ - u32 status; /* The status of the vchiq operation */ - u32 padding; -}; - -/* Send from VC to host to report version */ -struct mmal_msg_version { - u32 flags; - u32 major; - u32 minor; - u32 minimum; -}; - -/* request to VC to create component */ -struct mmal_msg_component_create { - u32 client_component; /* component context */ - char name[128]; - u32 pid; /* For debug */ -}; - -/* reply from VC to component creation request */ -struct mmal_msg_component_create_reply { - u32 status; /* enum mmal_msg_status - how does this differ to - * the one in the header? - */ - u32 component_handle; /* VideoCore handle for component */ - u32 input_num; /* Number of input ports */ - u32 output_num; /* Number of output ports */ - u32 clock_num; /* Number of clock ports */ -}; - -/* request to VC to destroy a component */ -struct mmal_msg_component_destroy { - u32 component_handle; -}; - -struct mmal_msg_component_destroy_reply { - u32 status; /* The component destruction status */ -}; - -/* request and reply to VC to enable a component */ -struct mmal_msg_component_enable { - u32 component_handle; -}; - -struct mmal_msg_component_enable_reply { - u32 status; /* The component enable status */ -}; - -/* request and reply to VC to disable a component */ -struct mmal_msg_component_disable { - u32 component_handle; -}; - -struct mmal_msg_component_disable_reply { - u32 status; /* The component disable status */ -}; - -/* request to VC to get port information */ -struct mmal_msg_port_info_get { - u32 component_handle; /* component handle port is associated with */ - u32 port_type; /* enum mmal_msg_port_type */ - u32 index; /* port index to query */ -}; - -/* reply from VC to get port info request */ -struct mmal_msg_port_info_get_reply { - u32 status; /* enum mmal_msg_status */ - u32 component_handle; /* component handle port is associated with */ - u32 port_type; /* enum mmal_msg_port_type */ - u32 port_index; /* port indexed in query */ - s32 found; /* unused */ - u32 port_handle; /* Handle to use for this port */ - struct mmal_port port; - struct mmal_es_format format; /* elementary stream format */ - union mmal_es_specific_format es; /* es type specific data */ - u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; /* es extra data */ -}; - -/* request to VC to set port information */ -struct mmal_msg_port_info_set { - u32 component_handle; - u32 port_type; /* enum mmal_msg_port_type */ - u32 port_index; /* port indexed in query */ - struct mmal_port port; - struct mmal_es_format format; - union mmal_es_specific_format es; - u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; -}; - -/* reply from VC to port info set request */ -struct mmal_msg_port_info_set_reply { - u32 status; - u32 component_handle; /* component handle port is associated with */ - u32 port_type; /* enum mmal_msg_port_type */ - u32 index; /* port indexed in query */ - s32 found; /* unused */ - u32 port_handle; /* Handle to use for this port */ - struct mmal_port port; - struct mmal_es_format format; - union mmal_es_specific_format es; - u8 extradata[MMAL_FORMAT_EXTRADATA_MAX_SIZE]; -}; - -/* port action requests that take a mmal_port as a parameter */ -struct mmal_msg_port_action_port { - u32 component_handle; - u32 port_handle; - u32 action; /* enum mmal_msg_port_action_type */ - struct mmal_port port; -}; - -/* port action requests that take handles as a parameter */ -struct mmal_msg_port_action_handle { - u32 component_handle; - u32 port_handle; - u32 action; /* enum mmal_msg_port_action_type */ - u32 connect_component_handle; - u32 connect_port_handle; -}; - -struct mmal_msg_port_action_reply { - u32 status; /* The port action operation status */ -}; - -/* MMAL buffer transfer */ - -/* Size of space reserved in a buffer message for short messages. */ -#define MMAL_VC_SHORT_DATA 128 - -/* Signals that the current payload is the end of the stream of data */ -#define MMAL_BUFFER_HEADER_FLAG_EOS BIT(0) -/* Signals that the start of the current payload starts a frame */ -#define MMAL_BUFFER_HEADER_FLAG_FRAME_START BIT(1) -/* Signals that the end of the current payload ends a frame */ -#define MMAL_BUFFER_HEADER_FLAG_FRAME_END BIT(2) -/* Signals that the current payload contains only complete frames (>1) */ -#define MMAL_BUFFER_HEADER_FLAG_FRAME \ - (MMAL_BUFFER_HEADER_FLAG_FRAME_START | \ - MMAL_BUFFER_HEADER_FLAG_FRAME_END) -/* Signals that the current payload is a keyframe (i.e. self decodable) */ -#define MMAL_BUFFER_HEADER_FLAG_KEYFRAME BIT(3) -/* - * Signals a discontinuity in the stream of data (e.g. after a seek). - * Can be used for instance by a decoder to reset its state - */ -#define MMAL_BUFFER_HEADER_FLAG_DISCONTINUITY BIT(4) -/* - * Signals a buffer containing some kind of config data for the component - * (e.g. codec config data) - */ -#define MMAL_BUFFER_HEADER_FLAG_CONFIG BIT(5) -/* Signals an encrypted payload */ -#define MMAL_BUFFER_HEADER_FLAG_ENCRYPTED BIT(6) -/* Signals a buffer containing side information */ -#define MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO BIT(7) -/* - * Signals a buffer which is the snapshot/postview image from a stills - * capture - */ -#define MMAL_BUFFER_HEADER_FLAGS_SNAPSHOT BIT(8) -/* Signals a buffer which contains data known to be corrupted */ -#define MMAL_BUFFER_HEADER_FLAG_CORRUPTED BIT(9) -/* Signals that a buffer failed to be transmitted */ -#define MMAL_BUFFER_HEADER_FLAG_TRANSMISSION_FAILED BIT(10) - -struct mmal_driver_buffer { - u32 magic; - u32 component_handle; - u32 port_handle; - u32 client_context; -}; - -/* buffer header */ -struct mmal_buffer_header { - u32 next; /* next header */ - u32 priv; /* framework private data */ - u32 cmd; - u32 data; - u32 alloc_size; - u32 length; - u32 offset; - u32 flags; - s64 pts; - s64 dts; - u32 type; - u32 user_data; -}; - -struct mmal_buffer_header_type_specific { - union { - struct { - u32 planes; - u32 offset[4]; - u32 pitch[4]; - u32 flags; - } video; - } u; -}; - -struct mmal_msg_buffer_from_host { - /* - *The front 32 bytes of the buffer header are copied - * back to us in the reply to allow for context. This - * area is used to store two mmal_driver_buffer structures to - * allow for multiple concurrent service users. - */ - /* control data */ - struct mmal_driver_buffer drvbuf; - - /* referenced control data for passthrough buffer management */ - struct mmal_driver_buffer drvbuf_ref; - struct mmal_buffer_header buffer_header; /* buffer header itself */ - struct mmal_buffer_header_type_specific buffer_header_type_specific; - s32 is_zero_copy; - s32 has_reference; - - /* allows short data to be xfered in control message */ - u32 payload_in_message; - u8 short_data[MMAL_VC_SHORT_DATA]; -}; - -/* port parameter setting */ - -#define MMAL_WORKER_PORT_PARAMETER_SPACE 96 - -struct mmal_msg_port_parameter_set { - u32 component_handle; /* component */ - u32 port_handle; /* port */ - u32 id; /* Parameter ID */ - u32 size; /* Parameter size */ - u32 value[MMAL_WORKER_PORT_PARAMETER_SPACE]; -}; - -struct mmal_msg_port_parameter_set_reply { - u32 status; /* enum mmal_msg_status todo: how does this - * differ to the one in the header? - */ -}; - -/* port parameter getting */ - -struct mmal_msg_port_parameter_get { - u32 component_handle; /* component */ - u32 port_handle; /* port */ - u32 id; /* Parameter ID */ - u32 size; /* Parameter size */ -}; - -struct mmal_msg_port_parameter_get_reply { - u32 status; /* Status of mmal_port_parameter_get call */ - u32 id; /* Parameter ID */ - u32 size; /* Parameter size */ - u32 value[MMAL_WORKER_PORT_PARAMETER_SPACE]; -}; - -/* event messages */ -#define MMAL_WORKER_EVENT_SPACE 256 - -struct mmal_msg_event_to_host { - u32 client_component; /* component context */ - - u32 port_type; - u32 port_num; - - u32 cmd; - u32 length; - u8 data[MMAL_WORKER_EVENT_SPACE]; - u32 delayed_buffer; -}; - -/* all mmal messages are serialised through this structure */ -struct mmal_msg { - /* header */ - struct mmal_msg_header h; - /* payload */ - union { - struct mmal_msg_version version; - - struct mmal_msg_component_create component_create; - struct mmal_msg_component_create_reply component_create_reply; - - struct mmal_msg_component_destroy component_destroy; - struct mmal_msg_component_destroy_reply component_destroy_reply; - - struct mmal_msg_component_enable component_enable; - struct mmal_msg_component_enable_reply component_enable_reply; - - struct mmal_msg_component_disable component_disable; - struct mmal_msg_component_disable_reply component_disable_reply; - - struct mmal_msg_port_info_get port_info_get; - struct mmal_msg_port_info_get_reply port_info_get_reply; - - struct mmal_msg_port_info_set port_info_set; - struct mmal_msg_port_info_set_reply port_info_set_reply; - - struct mmal_msg_port_action_port port_action_port; - struct mmal_msg_port_action_handle port_action_handle; - struct mmal_msg_port_action_reply port_action_reply; - - struct mmal_msg_buffer_from_host buffer_from_host; - - struct mmal_msg_port_parameter_set port_parameter_set; - struct mmal_msg_port_parameter_set_reply - port_parameter_set_reply; - struct mmal_msg_port_parameter_get - port_parameter_get; - struct mmal_msg_port_parameter_get_reply - port_parameter_get_reply; - - struct mmal_msg_event_to_host event_to_host; - - u8 payload[MMAL_MSG_MAX_PAYLOAD]; - } u; -}; -#endif diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h deleted file mode 100644 index a0cdd28101f2..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-parameters.h +++ /dev/null @@ -1,752 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 V4L2 driver - * - * Copyright © 2013 Raspberry Pi (Trading) Ltd. - * - * Authors: Vincent Sanders @ Collabora - * Dave Stevenson @ Broadcom - * (now dave.stevenson@raspberrypi.org) - * Simon Mellor @ Broadcom - * Luke Diamand @ Broadcom - */ - -/* common parameters */ - -/** @name Parameter groups - * Parameters are divided into groups, and then allocated sequentially within - * a group using an enum. - * @{ - */ - -#ifndef MMAL_PARAMETERS_H -#define MMAL_PARAMETERS_H - -#include <linux/math.h> - -/** Common parameter ID group, used with many types of component. */ -#define MMAL_PARAMETER_GROUP_COMMON (0 << 16) -/** Camera-specific parameter ID group. */ -#define MMAL_PARAMETER_GROUP_CAMERA (1 << 16) -/** Video-specific parameter ID group. */ -#define MMAL_PARAMETER_GROUP_VIDEO (2 << 16) -/** Audio-specific parameter ID group. */ -#define MMAL_PARAMETER_GROUP_AUDIO (3 << 16) -/** Clock-specific parameter ID group. */ -#define MMAL_PARAMETER_GROUP_CLOCK (4 << 16) -/** Miracast-specific parameter ID group. */ -#define MMAL_PARAMETER_GROUP_MIRACAST (5 << 16) - -/* Common parameters */ -enum mmal_parameter_common_type { - /**< Never a valid parameter ID */ - MMAL_PARAMETER_UNUSED = MMAL_PARAMETER_GROUP_COMMON, - - /**< MMAL_PARAMETER_ENCODING_T */ - MMAL_PARAMETER_SUPPORTED_ENCODINGS, - /**< MMAL_PARAMETER_URI_T */ - MMAL_PARAMETER_URI, - /** MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T */ - MMAL_PARAMETER_CHANGE_EVENT_REQUEST, - /** MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_ZERO_COPY, - /**< MMAL_PARAMETER_BUFFER_REQUIREMENTS_T */ - MMAL_PARAMETER_BUFFER_REQUIREMENTS, - /**< MMAL_PARAMETER_STATISTICS_T */ - MMAL_PARAMETER_STATISTICS, - /**< MMAL_PARAMETER_CORE_STATISTICS_T */ - MMAL_PARAMETER_CORE_STATISTICS, - /**< MMAL_PARAMETER_MEM_USAGE_T */ - MMAL_PARAMETER_MEM_USAGE, - /**< MMAL_PARAMETER_UINT32_T */ - MMAL_PARAMETER_BUFFER_FLAG_FILTER, - /**< MMAL_PARAMETER_SEEK_T */ - MMAL_PARAMETER_SEEK, - /**< MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_POWERMON_ENABLE, - /**< MMAL_PARAMETER_LOGGING_T */ - MMAL_PARAMETER_LOGGING, - /**< MMAL_PARAMETER_UINT64_T */ - MMAL_PARAMETER_SYSTEM_TIME, - /**< MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_NO_IMAGE_PADDING, -}; - -/* camera parameters */ - -enum mmal_parameter_camera_type { - /* 0 */ - /** @ref MMAL_PARAMETER_THUMBNAIL_CONFIG_T */ - MMAL_PARAMETER_THUMBNAIL_CONFIGURATION = - MMAL_PARAMETER_GROUP_CAMERA, - /**< Unused? */ - MMAL_PARAMETER_CAPTURE_QUALITY, - /**< @ref MMAL_PARAMETER_INT32_T */ - MMAL_PARAMETER_ROTATION, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_EXIF_DISABLE, - /**< @ref MMAL_PARAMETER_EXIF_T */ - MMAL_PARAMETER_EXIF, - /**< @ref MMAL_PARAM_AWBMODE_T */ - MMAL_PARAMETER_AWB_MODE, - /**< @ref MMAL_PARAMETER_IMAGEFX_T */ - MMAL_PARAMETER_IMAGE_EFFECT, - /**< @ref MMAL_PARAMETER_COLOURFX_T */ - MMAL_PARAMETER_COLOUR_EFFECT, - /**< @ref MMAL_PARAMETER_FLICKERAVOID_T */ - MMAL_PARAMETER_FLICKER_AVOID, - /**< @ref MMAL_PARAMETER_FLASH_T */ - MMAL_PARAMETER_FLASH, - /**< @ref MMAL_PARAMETER_REDEYE_T */ - MMAL_PARAMETER_REDEYE, - /**< @ref MMAL_PARAMETER_FOCUS_T */ - MMAL_PARAMETER_FOCUS, - /**< Unused? */ - MMAL_PARAMETER_FOCAL_LENGTHS, - /**< @ref MMAL_PARAMETER_INT32_T */ - MMAL_PARAMETER_EXPOSURE_COMP, - /**< @ref MMAL_PARAMETER_SCALEFACTOR_T */ - MMAL_PARAMETER_ZOOM, - /**< @ref MMAL_PARAMETER_MIRROR_T */ - MMAL_PARAMETER_MIRROR, - - /* 0x10 */ - /**< @ref MMAL_PARAMETER_UINT32_T */ - MMAL_PARAMETER_CAMERA_NUM, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_CAPTURE, - /**< @ref MMAL_PARAMETER_EXPOSUREMODE_T */ - MMAL_PARAMETER_EXPOSURE_MODE, - /**< @ref MMAL_PARAMETER_EXPOSUREMETERINGMODE_T */ - MMAL_PARAMETER_EXP_METERING_MODE, - /**< @ref MMAL_PARAMETER_FOCUS_STATUS_T */ - MMAL_PARAMETER_FOCUS_STATUS, - /**< @ref MMAL_PARAMETER_CAMERA_CONFIG_T */ - MMAL_PARAMETER_CAMERA_CONFIG, - /**< @ref MMAL_PARAMETER_CAPTURE_STATUS_T */ - MMAL_PARAMETER_CAPTURE_STATUS, - /**< @ref MMAL_PARAMETER_FACE_TRACK_T */ - MMAL_PARAMETER_FACE_TRACK, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_DRAW_BOX_FACES_AND_FOCUS, - /**< @ref MMAL_PARAMETER_UINT32_T */ - MMAL_PARAMETER_JPEG_Q_FACTOR, - /**< @ref MMAL_PARAMETER_FRAME_RATE_T */ - MMAL_PARAMETER_FRAME_RATE, - /**< @ref MMAL_PARAMETER_CAMERA_STC_MODE_T */ - MMAL_PARAMETER_USE_STC, - /**< @ref MMAL_PARAMETER_CAMERA_INFO_T */ - MMAL_PARAMETER_CAMERA_INFO, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_VIDEO_STABILISATION, - /**< @ref MMAL_PARAMETER_FACE_TRACK_RESULTS_T */ - MMAL_PARAMETER_FACE_TRACK_RESULTS, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_ENABLE_RAW_CAPTURE, - - /* 0x20 */ - /**< @ref MMAL_PARAMETER_URI_T */ - MMAL_PARAMETER_DPF_FILE, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_ENABLE_DPF_FILE, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_DPF_FAIL_IS_FATAL, - /**< @ref MMAL_PARAMETER_CAPTUREMODE_T */ - MMAL_PARAMETER_CAPTURE_MODE, - /**< @ref MMAL_PARAMETER_FOCUS_REGIONS_T */ - MMAL_PARAMETER_FOCUS_REGIONS, - /**< @ref MMAL_PARAMETER_INPUT_CROP_T */ - MMAL_PARAMETER_INPUT_CROP, - /**< @ref MMAL_PARAMETER_SENSOR_INFORMATION_T */ - MMAL_PARAMETER_SENSOR_INFORMATION, - /**< @ref MMAL_PARAMETER_FLASH_SELECT_T */ - MMAL_PARAMETER_FLASH_SELECT, - /**< @ref MMAL_PARAMETER_FIELD_OF_VIEW_T */ - MMAL_PARAMETER_FIELD_OF_VIEW, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_HIGH_DYNAMIC_RANGE, - /**< @ref MMAL_PARAMETER_DRC_T */ - MMAL_PARAMETER_DYNAMIC_RANGE_COMPRESSION, - /**< @ref MMAL_PARAMETER_ALGORITHM_CONTROL_T */ - MMAL_PARAMETER_ALGORITHM_CONTROL, - /**< @ref MMAL_PARAMETER_RATIONAL_T */ - MMAL_PARAMETER_SHARPNESS, - /**< @ref MMAL_PARAMETER_RATIONAL_T */ - MMAL_PARAMETER_CONTRAST, - /**< @ref MMAL_PARAMETER_RATIONAL_T */ - MMAL_PARAMETER_BRIGHTNESS, - /**< @ref MMAL_PARAMETER_RATIONAL_T */ - MMAL_PARAMETER_SATURATION, - - /* 0x30 */ - /**< @ref MMAL_PARAMETER_UINT32_T */ - MMAL_PARAMETER_ISO, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_ANTISHAKE, - /** @ref MMAL_PARAMETER_IMAGEFX_PARAMETERS_T */ - MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, - /** @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_CAMERA_BURST_CAPTURE, - /** @ref MMAL_PARAMETER_UINT32_T */ - MMAL_PARAMETER_CAMERA_MIN_ISO, - /** @ref MMAL_PARAMETER_CAMERA_USE_CASE_T */ - MMAL_PARAMETER_CAMERA_USE_CASE, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_CAPTURE_STATS_PASS, - /** @ref MMAL_PARAMETER_UINT32_T */ - MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG, - /** @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_ENABLE_REGISTER_FILE, - /** @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_REGISTER_FAIL_IS_FATAL, - /** @ref MMAL_PARAMETER_CONFIGFILE_T */ - MMAL_PARAMETER_CONFIGFILE_REGISTERS, - /** @ref MMAL_PARAMETER_CONFIGFILE_CHUNK_T */ - MMAL_PARAMETER_CONFIGFILE_CHUNK_REGISTERS, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_JPEG_ATTACH_LOG, - /**< @ref MMAL_PARAMETER_ZEROSHUTTERLAG_T */ - MMAL_PARAMETER_ZERO_SHUTTER_LAG, - /**< @ref MMAL_PARAMETER_FPS_RANGE_T */ - MMAL_PARAMETER_FPS_RANGE, - /**< @ref MMAL_PARAMETER_INT32_T */ - MMAL_PARAMETER_CAPTURE_EXPOSURE_COMP, - - /* 0x40 */ - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_SW_SHARPEN_DISABLE, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_FLASH_REQUIRED, - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_SW_SATURATION_DISABLE, - /**< Takes a @ref MMAL_PARAMETER_UINT32_T */ - MMAL_PARAMETER_SHUTTER_SPEED, - /**< Takes a @ref MMAL_PARAMETER_AWB_GAINS_T */ - MMAL_PARAMETER_CUSTOM_AWB_GAINS, -}; - -enum mmal_parameter_camera_config_timestamp_mode { - MMAL_PARAM_TIMESTAMP_MODE_ZERO = 0, /* Always timestamp frames as 0 */ - MMAL_PARAM_TIMESTAMP_MODE_RAW_STC, /* Use the raw STC value - * for the frame timestamp - */ - MMAL_PARAM_TIMESTAMP_MODE_RESET_STC, /* Use the STC timestamp - * but subtract the - * timestamp of the first - * frame sent to give a - * zero based timestamp. - */ -}; - -struct mmal_parameter_fps_range { - /**< Low end of the permitted framerate range */ - struct s32_fract fps_low; - /**< High end of the permitted framerate range */ - struct s32_fract fps_high; -}; - -/* camera configuration parameter */ -struct mmal_parameter_camera_config { - /* Parameters for setting up the image pools */ - u32 max_stills_w; /* Max size of stills capture */ - u32 max_stills_h; - u32 stills_yuv422; /* Allow YUV422 stills capture */ - u32 one_shot_stills; /* Continuous or one shot stills captures. */ - - u32 max_preview_video_w; /* Max size of the preview or video - * capture frames - */ - u32 max_preview_video_h; - u32 num_preview_video_frames; - - /** Sets the height of the circular buffer for stills capture. */ - u32 stills_capture_circular_buffer_height; - - /** Allows preview/encode to resume as fast as possible after the stills - * input frame has been received, and then processes the still frame in - * the background whilst preview/encode has resumed. - * Actual mode is controlled by MMAL_PARAMETER_CAPTURE_MODE. - */ - u32 fast_preview_resume; - - /** Selects algorithm for timestamping frames if - * there is no clock component connected. - * enum mmal_parameter_camera_config_timestamp_mode - */ - s32 use_stc_timestamp; -}; - -enum mmal_parameter_exposuremode { - MMAL_PARAM_EXPOSUREMODE_OFF, - MMAL_PARAM_EXPOSUREMODE_AUTO, - MMAL_PARAM_EXPOSUREMODE_NIGHT, - MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW, - MMAL_PARAM_EXPOSUREMODE_BACKLIGHT, - MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT, - MMAL_PARAM_EXPOSUREMODE_SPORTS, - MMAL_PARAM_EXPOSUREMODE_SNOW, - MMAL_PARAM_EXPOSUREMODE_BEACH, - MMAL_PARAM_EXPOSUREMODE_VERYLONG, - MMAL_PARAM_EXPOSUREMODE_FIXEDFPS, - MMAL_PARAM_EXPOSUREMODE_ANTISHAKE, - MMAL_PARAM_EXPOSUREMODE_FIREWORKS, -}; - -enum mmal_parameter_exposuremeteringmode { - MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE, - MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT, - MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT, - MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX, -}; - -enum mmal_parameter_awbmode { - MMAL_PARAM_AWBMODE_OFF, - MMAL_PARAM_AWBMODE_AUTO, - MMAL_PARAM_AWBMODE_SUNLIGHT, - MMAL_PARAM_AWBMODE_CLOUDY, - MMAL_PARAM_AWBMODE_SHADE, - MMAL_PARAM_AWBMODE_TUNGSTEN, - MMAL_PARAM_AWBMODE_FLUORESCENT, - MMAL_PARAM_AWBMODE_INCANDESCENT, - MMAL_PARAM_AWBMODE_FLASH, - MMAL_PARAM_AWBMODE_HORIZON, -}; - -enum mmal_parameter_imagefx { - MMAL_PARAM_IMAGEFX_NONE, - MMAL_PARAM_IMAGEFX_NEGATIVE, - MMAL_PARAM_IMAGEFX_SOLARIZE, - MMAL_PARAM_IMAGEFX_POSTERIZE, - MMAL_PARAM_IMAGEFX_WHITEBOARD, - MMAL_PARAM_IMAGEFX_BLACKBOARD, - MMAL_PARAM_IMAGEFX_SKETCH, - MMAL_PARAM_IMAGEFX_DENOISE, - MMAL_PARAM_IMAGEFX_EMBOSS, - MMAL_PARAM_IMAGEFX_OILPAINT, - MMAL_PARAM_IMAGEFX_HATCH, - MMAL_PARAM_IMAGEFX_GPEN, - MMAL_PARAM_IMAGEFX_PASTEL, - MMAL_PARAM_IMAGEFX_WATERCOLOUR, - MMAL_PARAM_IMAGEFX_FILM, - MMAL_PARAM_IMAGEFX_BLUR, - MMAL_PARAM_IMAGEFX_SATURATION, - MMAL_PARAM_IMAGEFX_COLOURSWAP, - MMAL_PARAM_IMAGEFX_WASHEDOUT, - MMAL_PARAM_IMAGEFX_POSTERISE, - MMAL_PARAM_IMAGEFX_COLOURPOINT, - MMAL_PARAM_IMAGEFX_COLOURBALANCE, - MMAL_PARAM_IMAGEFX_CARTOON, -}; - -enum MMAL_PARAM_FLICKERAVOID { - MMAL_PARAM_FLICKERAVOID_OFF, - MMAL_PARAM_FLICKERAVOID_AUTO, - MMAL_PARAM_FLICKERAVOID_50HZ, - MMAL_PARAM_FLICKERAVOID_60HZ, - MMAL_PARAM_FLICKERAVOID_MAX = 0x7FFFFFFF -}; - -struct mmal_parameter_awbgains { - struct s32_fract r_gain; /**< Red gain */ - struct s32_fract b_gain; /**< Blue gain */ -}; - -/** Manner of video rate control */ -enum mmal_parameter_rate_control_mode { - MMAL_VIDEO_RATECONTROL_DEFAULT, - MMAL_VIDEO_RATECONTROL_VARIABLE, - MMAL_VIDEO_RATECONTROL_CONSTANT, - MMAL_VIDEO_RATECONTROL_VARIABLE_SKIP_FRAMES, - MMAL_VIDEO_RATECONTROL_CONSTANT_SKIP_FRAMES -}; - -enum mmal_video_profile { - MMAL_VIDEO_PROFILE_H263_BASELINE, - MMAL_VIDEO_PROFILE_H263_H320CODING, - MMAL_VIDEO_PROFILE_H263_BACKWARDCOMPATIBLE, - MMAL_VIDEO_PROFILE_H263_ISWV2, - MMAL_VIDEO_PROFILE_H263_ISWV3, - MMAL_VIDEO_PROFILE_H263_HIGHCOMPRESSION, - MMAL_VIDEO_PROFILE_H263_INTERNET, - MMAL_VIDEO_PROFILE_H263_INTERLACE, - MMAL_VIDEO_PROFILE_H263_HIGHLATENCY, - MMAL_VIDEO_PROFILE_MP4V_SIMPLE, - MMAL_VIDEO_PROFILE_MP4V_SIMPLESCALABLE, - MMAL_VIDEO_PROFILE_MP4V_CORE, - MMAL_VIDEO_PROFILE_MP4V_MAIN, - MMAL_VIDEO_PROFILE_MP4V_NBIT, - MMAL_VIDEO_PROFILE_MP4V_SCALABLETEXTURE, - MMAL_VIDEO_PROFILE_MP4V_SIMPLEFACE, - MMAL_VIDEO_PROFILE_MP4V_SIMPLEFBA, - MMAL_VIDEO_PROFILE_MP4V_BASICANIMATED, - MMAL_VIDEO_PROFILE_MP4V_HYBRID, - MMAL_VIDEO_PROFILE_MP4V_ADVANCEDREALTIME, - MMAL_VIDEO_PROFILE_MP4V_CORESCALABLE, - MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCODING, - MMAL_VIDEO_PROFILE_MP4V_ADVANCEDCORE, - MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSCALABLE, - MMAL_VIDEO_PROFILE_MP4V_ADVANCEDSIMPLE, - MMAL_VIDEO_PROFILE_H264_BASELINE, - MMAL_VIDEO_PROFILE_H264_MAIN, - MMAL_VIDEO_PROFILE_H264_EXTENDED, - MMAL_VIDEO_PROFILE_H264_HIGH, - MMAL_VIDEO_PROFILE_H264_HIGH10, - MMAL_VIDEO_PROFILE_H264_HIGH422, - MMAL_VIDEO_PROFILE_H264_HIGH444, - MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE, - MMAL_VIDEO_PROFILE_DUMMY = 0x7FFFFFFF -}; - -enum mmal_video_level { - MMAL_VIDEO_LEVEL_H263_10, - MMAL_VIDEO_LEVEL_H263_20, - MMAL_VIDEO_LEVEL_H263_30, - MMAL_VIDEO_LEVEL_H263_40, - MMAL_VIDEO_LEVEL_H263_45, - MMAL_VIDEO_LEVEL_H263_50, - MMAL_VIDEO_LEVEL_H263_60, - MMAL_VIDEO_LEVEL_H263_70, - MMAL_VIDEO_LEVEL_MP4V_0, - MMAL_VIDEO_LEVEL_MP4V_0b, - MMAL_VIDEO_LEVEL_MP4V_1, - MMAL_VIDEO_LEVEL_MP4V_2, - MMAL_VIDEO_LEVEL_MP4V_3, - MMAL_VIDEO_LEVEL_MP4V_4, - MMAL_VIDEO_LEVEL_MP4V_4a, - MMAL_VIDEO_LEVEL_MP4V_5, - MMAL_VIDEO_LEVEL_MP4V_6, - MMAL_VIDEO_LEVEL_H264_1, - MMAL_VIDEO_LEVEL_H264_1b, - MMAL_VIDEO_LEVEL_H264_11, - MMAL_VIDEO_LEVEL_H264_12, - MMAL_VIDEO_LEVEL_H264_13, - MMAL_VIDEO_LEVEL_H264_2, - MMAL_VIDEO_LEVEL_H264_21, - MMAL_VIDEO_LEVEL_H264_22, - MMAL_VIDEO_LEVEL_H264_3, - MMAL_VIDEO_LEVEL_H264_31, - MMAL_VIDEO_LEVEL_H264_32, - MMAL_VIDEO_LEVEL_H264_4, - MMAL_VIDEO_LEVEL_H264_41, - MMAL_VIDEO_LEVEL_H264_42, - MMAL_VIDEO_LEVEL_H264_5, - MMAL_VIDEO_LEVEL_H264_51, - MMAL_VIDEO_LEVEL_DUMMY = 0x7FFFFFFF -}; - -struct mmal_parameter_video_profile { - enum mmal_video_profile profile; - enum mmal_video_level level; -}; - -/* video parameters */ - -enum mmal_parameter_video_type { - /** @ref MMAL_DISPLAYREGION_T */ - MMAL_PARAMETER_DISPLAYREGION = MMAL_PARAMETER_GROUP_VIDEO, - - /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */ - MMAL_PARAMETER_SUPPORTED_PROFILES, - - /** @ref MMAL_PARAMETER_VIDEO_PROFILE_T */ - MMAL_PARAMETER_PROFILE, - - /** @ref MMAL_PARAMETER_UINT32_T */ - MMAL_PARAMETER_INTRAPERIOD, - - /** @ref MMAL_PARAMETER_VIDEO_RATECONTROL_T */ - MMAL_PARAMETER_RATECONTROL, - - /** @ref MMAL_PARAMETER_VIDEO_NALUNITFORMAT_T */ - MMAL_PARAMETER_NALUNITFORMAT, - - /** @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_MINIMISE_FRAGMENTATION, - - /** @ref MMAL_PARAMETER_UINT32_T. - * Setting the value to zero resets to the default (one slice per - * frame). - */ - MMAL_PARAMETER_MB_ROWS_PER_SLICE, - - /** @ref MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION_T */ - MMAL_PARAMETER_VIDEO_LEVEL_EXTENSION, - - /** @ref MMAL_PARAMETER_VIDEO_EEDE_ENABLE_T */ - MMAL_PARAMETER_VIDEO_EEDE_ENABLE, - - /** @ref MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE_T */ - MMAL_PARAMETER_VIDEO_EEDE_LOSSRATE, - - /** @ref MMAL_PARAMETER_BOOLEAN_T. Request an I-frame. */ - MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME, - /** @ref MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T */ - MMAL_PARAMETER_VIDEO_INTRA_REFRESH, - - /** @ref MMAL_PARAMETER_BOOLEAN_T. */ - MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, - - /** @ref MMAL_PARAMETER_UINT32_T. Run-time bit rate control */ - MMAL_PARAMETER_VIDEO_BIT_RATE, - - /** @ref MMAL_PARAMETER_FRAME_RATE_T */ - MMAL_PARAMETER_VIDEO_FRAME_RATE, - - /** @ref MMAL_PARAMETER_UINT32_T. */ - MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, - - /** @ref MMAL_PARAMETER_UINT32_T. */ - MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, - - /** @ref MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL_T. */ - MMAL_PARAMETER_VIDEO_ENCODE_RC_MODEL, - - MMAL_PARAMETER_EXTRA_BUFFERS, /**< @ref MMAL_PARAMETER_UINT32_T. */ - /** @ref MMAL_PARAMETER_UINT32_T. - * Changing this parameter from the default can reduce frame rate - * because image buffers need to be re-pitched. - */ - MMAL_PARAMETER_VIDEO_ALIGN_HORIZ, - - /** @ref MMAL_PARAMETER_UINT32_T. - * Changing this parameter from the default can reduce frame rate - * because image buffers need to be re-pitched. - */ - MMAL_PARAMETER_VIDEO_ALIGN_VERT, - - /** @ref MMAL_PARAMETER_BOOLEAN_T. */ - MMAL_PARAMETER_VIDEO_DROPPABLE_PFRAMES, - - /** @ref MMAL_PARAMETER_UINT32_T. */ - MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, - - /**< @ref MMAL_PARAMETER_UINT32_T. */ - MMAL_PARAMETER_VIDEO_ENCODE_QP_P, - - /**< @ref MMAL_PARAMETER_UINT32_T. */ - MMAL_PARAMETER_VIDEO_ENCODE_RC_SLICE_DQUANT, - - /** @ref MMAL_PARAMETER_UINT32_T */ - MMAL_PARAMETER_VIDEO_ENCODE_FRAME_LIMIT_BITS, - - /** @ref MMAL_PARAMETER_UINT32_T. */ - MMAL_PARAMETER_VIDEO_ENCODE_PEAK_RATE, - - /* H264 specific parameters */ - - /** @ref MMAL_PARAMETER_BOOLEAN_T. */ - MMAL_PARAMETER_VIDEO_ENCODE_H264_DISABLE_CABAC, - - /** @ref MMAL_PARAMETER_BOOLEAN_T. */ - MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_LATENCY, - - /** @ref MMAL_PARAMETER_BOOLEAN_T. */ - MMAL_PARAMETER_VIDEO_ENCODE_H264_AU_DELIMITERS, - - /** @ref MMAL_PARAMETER_UINT32_T. */ - MMAL_PARAMETER_VIDEO_ENCODE_H264_DEBLOCK_IDC, - - /** @ref MMAL_PARAMETER_VIDEO_ENCODER_H264_MB_INTRA_MODES_T. */ - MMAL_PARAMETER_VIDEO_ENCODE_H264_MB_INTRA_MODE, - - /** @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_VIDEO_ENCODE_HEADER_ON_OPEN, - - /** @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_VIDEO_ENCODE_PRECODE_FOR_QP, - - /** @ref MMAL_PARAMETER_VIDEO_DRM_INIT_INFO_T. */ - MMAL_PARAMETER_VIDEO_DRM_INIT_INFO, - - /** @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_VIDEO_TIMESTAMP_FIFO, - - /** @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT, - - /** @ref MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER_T. */ - MMAL_PARAMETER_VIDEO_DRM_PROTECT_BUFFER, - - /** @ref MMAL_PARAMETER_BYTES_T */ - MMAL_PARAMETER_VIDEO_DECODE_CONFIG_VD3, - - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_VIDEO_ENCODE_H264_VCL_HRD_PARAMETERS, - - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_VIDEO_ENCODE_H264_LOW_DELAY_HRD_FLAG, - - /**< @ref MMAL_PARAMETER_BOOLEAN_T */ - MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER -}; - -/** Valid mirror modes */ -enum mmal_parameter_mirror { - MMAL_PARAM_MIRROR_NONE, - MMAL_PARAM_MIRROR_VERTICAL, - MMAL_PARAM_MIRROR_HORIZONTAL, - MMAL_PARAM_MIRROR_BOTH, -}; - -enum mmal_parameter_displaytransform { - MMAL_DISPLAY_ROT0 = 0, - MMAL_DISPLAY_MIRROR_ROT0 = 1, - MMAL_DISPLAY_MIRROR_ROT180 = 2, - MMAL_DISPLAY_ROT180 = 3, - MMAL_DISPLAY_MIRROR_ROT90 = 4, - MMAL_DISPLAY_ROT270 = 5, - MMAL_DISPLAY_ROT90 = 6, - MMAL_DISPLAY_MIRROR_ROT270 = 7, -}; - -enum mmal_parameter_displaymode { - MMAL_DISPLAY_MODE_FILL = 0, - MMAL_DISPLAY_MODE_LETTERBOX = 1, -}; - -enum mmal_parameter_displayset { - MMAL_DISPLAY_SET_NONE = 0, - MMAL_DISPLAY_SET_NUM = 1, - MMAL_DISPLAY_SET_FULLSCREEN = 2, - MMAL_DISPLAY_SET_TRANSFORM = 4, - MMAL_DISPLAY_SET_DEST_RECT = 8, - MMAL_DISPLAY_SET_SRC_RECT = 0x10, - MMAL_DISPLAY_SET_MODE = 0x20, - MMAL_DISPLAY_SET_PIXEL = 0x40, - MMAL_DISPLAY_SET_NOASPECT = 0x80, - MMAL_DISPLAY_SET_LAYER = 0x100, - MMAL_DISPLAY_SET_COPYPROTECT = 0x200, - MMAL_DISPLAY_SET_ALPHA = 0x400, -}; - -/* rectangle, used lots so it gets its own struct */ -struct vchiq_mmal_rect { - s32 x; - s32 y; - s32 width; - s32 height; -}; - -struct mmal_parameter_displayregion { - /** Bitfield that indicates which fields are set and should be - * used. All other fields will maintain their current value. - * \ref MMAL_DISPLAYSET_T defines the bits that can be - * combined. - */ - u32 set; - - /** Describes the display output device, with 0 typically - * being a directly connected LCD display. The actual values - * will depend on the hardware. Code using hard-wired numbers - * (e.g. 2) is certain to fail. - */ - - u32 display_num; - /** Indicates that we are using the full device screen area, - * rather than a window of the display. If zero, then - * dest_rect is used to specify a region of the display to - * use. - */ - - s32 fullscreen; - /** Indicates any rotation or flipping used to map frames onto - * the natural display orientation. - */ - u32 transform; /* enum mmal_parameter_displaytransform */ - - /** Where to display the frame within the screen, if - * fullscreen is zero. - */ - struct vchiq_mmal_rect dest_rect; - - /** Indicates which area of the frame to display. If all - * values are zero, the whole frame will be used. - */ - struct vchiq_mmal_rect src_rect; - - /** If set to non-zero, indicates that any display scaling - * should disregard the aspect ratio of the frame region being - * displayed. - */ - s32 noaspect; - - /** Indicates how the image should be scaled to fit the - * display. \code MMAL_DISPLAY_MODE_FILL \endcode indicates - * that the image should fill the screen by potentially - * cropping the frames. Setting \code mode \endcode to \code - * MMAL_DISPLAY_MODE_LETTERBOX \endcode indicates that all the - * source region should be displayed and black bars added if - * necessary. - */ - u32 mode; /* enum mmal_parameter_displaymode */ - - /** If non-zero, defines the width of a source pixel relative - * to \code pixel_y \endcode. If zero, then pixels default to - * being square. - */ - u32 pixel_x; - - /** If non-zero, defines the height of a source pixel relative - * to \code pixel_x \endcode. If zero, then pixels default to - * being square. - */ - u32 pixel_y; - - /** Sets the relative depth of the images, with greater values - * being in front of smaller values. - */ - u32 layer; - - /** Set to non-zero to ensure copy protection is used on - * output. - */ - s32 copyprotect_required; - - /** Level of opacity of the layer, where zero is fully - * transparent and 255 is fully opaque. - */ - u32 alpha; -}; - -#define MMAL_MAX_IMAGEFX_PARAMETERS 5 - -struct mmal_parameter_imagefx_parameters { - enum mmal_parameter_imagefx effect; - u32 num_effect_params; - u32 effect_parameter[MMAL_MAX_IMAGEFX_PARAMETERS]; -}; - -#define MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS 4 -#define MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES 2 -#define MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN 16 - -struct mmal_parameter_camera_info_camera { - u32 port_id; - u32 max_width; - u32 max_height; - u32 lens_present; - u8 camera_name[MMAL_PARAMETER_CAMERA_INFO_MAX_STR_LEN]; -}; - -enum mmal_parameter_camera_info_flash_type { - /* Make values explicit to ensure they match values in config ini */ - MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_XENON = 0, - MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_LED = 1, - MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_OTHER = 2, - MMAL_PARAMETER_CAMERA_INFO_FLASH_TYPE_MAX = 0x7FFFFFFF -}; - -struct mmal_parameter_camera_info_flash { - enum mmal_parameter_camera_info_flash_type flash_type; -}; - -struct mmal_parameter_camera_info { - u32 num_cameras; - u32 num_flashes; - struct mmal_parameter_camera_info_camera - cameras[MMAL_PARAMETER_CAMERA_INFO_MAX_CAMERAS]; - struct mmal_parameter_camera_info_flash - flashes[MMAL_PARAMETER_CAMERA_INFO_MAX_FLASHES]; -}; - -#endif diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c deleted file mode 100644 index c2b5a37915f2..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c +++ /dev/null @@ -1,1948 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Broadcom BCM2835 V4L2 driver - * - * Copyright © 2013 Raspberry Pi (Trading) Ltd. - * - * Authors: Vincent Sanders @ Collabora - * Dave Stevenson @ Broadcom - * (now dave.stevenson@raspberrypi.org) - * Simon Mellor @ Broadcom - * Luke Diamand @ Broadcom - * - * V4L2 driver MMAL vchiq interface code - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/completion.h> -#include <linux/vmalloc.h> -#include <media/videobuf2-vmalloc.h> - -#include "../include/linux/raspberrypi/vchiq.h" -#include "../interface/vchiq_arm/vchiq_arm.h" -#include "mmal-common.h" -#include "mmal-vchiq.h" -#include "mmal-msg.h" - -/* - * maximum number of components supported. - * This matches the maximum permitted by default on the VPU - */ -#define VCHIQ_MMAL_MAX_COMPONENTS 64 - -/* - * Timeout for synchronous msg responses in seconds. - * Helpful to increase this if stopping in the VPU debugger. - */ -#define SYNC_MSG_TIMEOUT 3 - -/*#define FULL_MSG_DUMP 1*/ - -#ifdef DEBUG -static const char *const msg_type_names[] = { - "UNKNOWN", - "QUIT", - "SERVICE_CLOSED", - "GET_VERSION", - "COMPONENT_CREATE", - "COMPONENT_DESTROY", - "COMPONENT_ENABLE", - "COMPONENT_DISABLE", - "PORT_INFO_GET", - "PORT_INFO_SET", - "PORT_ACTION", - "BUFFER_FROM_HOST", - "BUFFER_TO_HOST", - "GET_STATS", - "PORT_PARAMETER_SET", - "PORT_PARAMETER_GET", - "EVENT_TO_HOST", - "GET_CORE_STATS_FOR_PORT", - "OPAQUE_ALLOCATOR", - "CONSUME_MEM", - "LMK", - "OPAQUE_ALLOCATOR_DESC", - "DRM_GET_LHS32", - "DRM_GET_TIME", - "BUFFER_FROM_HOST_ZEROLEN", - "PORT_FLUSH", - "HOST_LOG", -}; -#endif - -static const char *const port_action_type_names[] = { - "UNKNOWN", - "ENABLE", - "DISABLE", - "FLUSH", - "CONNECT", - "DISCONNECT", - "SET_REQUIREMENTS", -}; - -#if defined(DEBUG) -#if defined(FULL_MSG_DUMP) -#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) \ - do { \ - pr_debug(TITLE" type:%s(%d) length:%d\n", \ - msg_type_names[(MSG)->h.type], \ - (MSG)->h.type, (MSG_LEN)); \ - print_hex_dump(KERN_DEBUG, "<<h: ", DUMP_PREFIX_OFFSET, \ - 16, 4, (MSG), \ - sizeof(struct mmal_msg_header), 1); \ - print_hex_dump(KERN_DEBUG, "<<p: ", DUMP_PREFIX_OFFSET, \ - 16, 4, \ - ((u8 *)(MSG)) + sizeof(struct mmal_msg_header),\ - (MSG_LEN) - sizeof(struct mmal_msg_header), 1); \ - } while (0) -#else -#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) \ - { \ - pr_debug(TITLE" type:%s(%d) length:%d\n", \ - msg_type_names[(MSG)->h.type], \ - (MSG)->h.type, (MSG_LEN)); \ - } -#endif -#else -#define DBG_DUMP_MSG(MSG, MSG_LEN, TITLE) -#endif - -struct vchiq_mmal_instance; - -/* normal message context */ -struct mmal_msg_context { - struct vchiq_mmal_instance *instance; - - /* Index in the context_map idr so that we can find the - * mmal_msg_context again when servicing the VCHI reply. - */ - int handle; - - union { - struct { - /* work struct for buffer_cb callback */ - struct work_struct work; - /* work struct for deferred callback */ - struct work_struct buffer_to_host_work; - /* mmal instance */ - struct vchiq_mmal_instance *instance; - /* mmal port */ - struct vchiq_mmal_port *port; - /* actual buffer used to store bulk reply */ - struct mmal_buffer *buffer; - /* amount of buffer used */ - unsigned long buffer_used; - /* MMAL buffer flags */ - u32 mmal_flags; - /* Presentation and Decode timestamps */ - s64 pts; - s64 dts; - - int status; /* context status */ - - } bulk; /* bulk data */ - - struct { - /* message handle to release */ - struct vchiq_header *msg_handle; - /* pointer to received message */ - struct mmal_msg *msg; - /* received message length */ - u32 msg_len; - /* completion upon reply */ - struct completion cmplt; - } sync; /* synchronous response */ - } u; - -}; - -struct vchiq_mmal_instance { - unsigned int service_handle; - - /* ensure serialised access to service */ - struct mutex vchiq_mutex; - - struct idr context_map; - /* protect accesses to context_map */ - struct mutex context_map_lock; - - struct vchiq_mmal_component component[VCHIQ_MMAL_MAX_COMPONENTS]; - - /* ordered workqueue to process all bulk operations */ - struct workqueue_struct *bulk_wq; - - /* handle for a vchiq instance */ - struct vchiq_instance *vchiq_instance; -}; - -static struct mmal_msg_context * -get_msg_context(struct vchiq_mmal_instance *instance) -{ - struct mmal_msg_context *msg_context; - int handle; - - /* todo: should this be allocated from a pool to avoid kzalloc */ - msg_context = kzalloc(sizeof(*msg_context), GFP_KERNEL); - - if (!msg_context) - return ERR_PTR(-ENOMEM); - - /* Create an ID that will be passed along with our message so - * that when we service the VCHI reply, we can look up what - * message is being replied to. - */ - mutex_lock(&instance->context_map_lock); - handle = idr_alloc(&instance->context_map, msg_context, - 0, 0, GFP_KERNEL); - mutex_unlock(&instance->context_map_lock); - - if (handle < 0) { - kfree(msg_context); - return ERR_PTR(handle); - } - - msg_context->instance = instance; - msg_context->handle = handle; - - return msg_context; -} - -static struct mmal_msg_context * -lookup_msg_context(struct vchiq_mmal_instance *instance, int handle) -{ - return idr_find(&instance->context_map, handle); -} - -static void -release_msg_context(struct mmal_msg_context *msg_context) -{ - struct vchiq_mmal_instance *instance = msg_context->instance; - - mutex_lock(&instance->context_map_lock); - idr_remove(&instance->context_map, msg_context->handle); - mutex_unlock(&instance->context_map_lock); - kfree(msg_context); -} - -/* deals with receipt of event to host message */ -static void event_to_host_cb(struct vchiq_mmal_instance *instance, - struct mmal_msg *msg, u32 msg_len) -{ - pr_debug("unhandled event\n"); - pr_debug("component:%u port type:%d num:%d cmd:0x%x length:%d\n", - msg->u.event_to_host.client_component, - msg->u.event_to_host.port_type, - msg->u.event_to_host.port_num, - msg->u.event_to_host.cmd, msg->u.event_to_host.length); -} - -/* workqueue scheduled callback - * - * we do this because it is important we do not call any other vchiq - * sync calls from within the message delivery thread - */ -static void buffer_work_cb(struct work_struct *work) -{ - struct mmal_msg_context *msg_context = - container_of(work, struct mmal_msg_context, u.bulk.work); - struct mmal_buffer *buffer = msg_context->u.bulk.buffer; - - if (!buffer) { - pr_err("%s: ctx: %p, No mmal buffer to pass details\n", - __func__, msg_context); - return; - } - - buffer->length = msg_context->u.bulk.buffer_used; - buffer->mmal_flags = msg_context->u.bulk.mmal_flags; - buffer->dts = msg_context->u.bulk.dts; - buffer->pts = msg_context->u.bulk.pts; - - atomic_dec(&msg_context->u.bulk.port->buffers_with_vpu); - - msg_context->u.bulk.port->buffer_cb(msg_context->u.bulk.instance, - msg_context->u.bulk.port, - msg_context->u.bulk.status, - msg_context->u.bulk.buffer); -} - -/* workqueue scheduled callback to handle receiving buffers - * - * VCHI will allow up to 4 bulk receives to be scheduled before blocking. - * If we block in the service_callback context then we can't process the - * VCHI_CALLBACK_BULK_RECEIVED message that would otherwise allow the blocked - * vchiq_bulk_receive() call to complete. - */ -static void buffer_to_host_work_cb(struct work_struct *work) -{ - struct mmal_msg_context *msg_context = - container_of(work, struct mmal_msg_context, - u.bulk.buffer_to_host_work); - struct vchiq_mmal_instance *instance = msg_context->instance; - unsigned long len = msg_context->u.bulk.buffer_used; - int ret; - - if (!len) - /* Dummy receive to ensure the buffers remain in order */ - len = 8; - /* queue the bulk submission */ - vchiq_use_service(instance->vchiq_instance, instance->service_handle); - ret = vchiq_bulk_receive(instance->vchiq_instance, instance->service_handle, - msg_context->u.bulk.buffer->buffer, - /* Actual receive needs to be a multiple - * of 4 bytes - */ - (len + 3) & ~3, - msg_context, - VCHIQ_BULK_MODE_CALLBACK); - - vchiq_release_service(instance->vchiq_instance, instance->service_handle); - - if (ret != 0) - pr_err("%s: ctx: %p, vchiq_bulk_receive failed %d\n", - __func__, msg_context, ret); -} - -/* enqueue a bulk receive for a given message context */ -static int bulk_receive(struct vchiq_mmal_instance *instance, - struct mmal_msg *msg, - struct mmal_msg_context *msg_context) -{ - unsigned long rd_len; - - rd_len = msg->u.buffer_from_host.buffer_header.length; - - if (!msg_context->u.bulk.buffer) { - pr_err("bulk.buffer not configured - error in buffer_from_host\n"); - - /* todo: this is a serious error, we should never have - * committed a buffer_to_host operation to the mmal - * port without the buffer to back it up (underflow - * handling) and there is no obvious way to deal with - * this - how is the mmal service going to react when - * we fail to do the xfer and reschedule a buffer when - * it arrives? perhaps a starved flag to indicate a - * waiting bulk receive? - */ - - return -EINVAL; - } - - /* ensure we do not overrun the available buffer */ - if (rd_len > msg_context->u.bulk.buffer->buffer_size) { - rd_len = msg_context->u.bulk.buffer->buffer_size; - pr_warn("short read as not enough receive buffer space\n"); - /* todo: is this the correct response, what happens to - * the rest of the message data? - */ - } - - /* store length */ - msg_context->u.bulk.buffer_used = rd_len; - msg_context->u.bulk.dts = msg->u.buffer_from_host.buffer_header.dts; - msg_context->u.bulk.pts = msg->u.buffer_from_host.buffer_header.pts; - - queue_work(msg_context->instance->bulk_wq, - &msg_context->u.bulk.buffer_to_host_work); - - return 0; -} - -/* data in message, memcpy from packet into output buffer */ -static int inline_receive(struct vchiq_mmal_instance *instance, - struct mmal_msg *msg, - struct mmal_msg_context *msg_context) -{ - memcpy(msg_context->u.bulk.buffer->buffer, - msg->u.buffer_from_host.short_data, - msg->u.buffer_from_host.payload_in_message); - - msg_context->u.bulk.buffer_used = - msg->u.buffer_from_host.payload_in_message; - - return 0; -} - -/* queue the buffer availability with MMAL_MSG_TYPE_BUFFER_FROM_HOST */ -static int -buffer_from_host(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, struct mmal_buffer *buf) -{ - struct mmal_msg_context *msg_context; - struct mmal_msg m; - int ret; - - if (!port->enabled) - return -EINVAL; - - pr_debug("instance:%u buffer:%p\n", instance->service_handle, buf); - - /* get context */ - if (!buf->msg_context) { - pr_err("%s: msg_context not allocated, buf %p\n", __func__, - buf); - return -EINVAL; - } - msg_context = buf->msg_context; - - /* store bulk message context for when data arrives */ - msg_context->u.bulk.instance = instance; - msg_context->u.bulk.port = port; - msg_context->u.bulk.buffer = buf; - msg_context->u.bulk.buffer_used = 0; - - /* initialise work structure ready to schedule callback */ - INIT_WORK(&msg_context->u.bulk.work, buffer_work_cb); - INIT_WORK(&msg_context->u.bulk.buffer_to_host_work, - buffer_to_host_work_cb); - - atomic_inc(&port->buffers_with_vpu); - - /* prep the buffer from host message */ - memset(&m, 0xbc, sizeof(m)); /* just to make debug clearer */ - - m.h.type = MMAL_MSG_TYPE_BUFFER_FROM_HOST; - m.h.magic = MMAL_MAGIC; - m.h.context = msg_context->handle; - m.h.status = 0; - - /* drvbuf is our private data passed back */ - m.u.buffer_from_host.drvbuf.magic = MMAL_MAGIC; - m.u.buffer_from_host.drvbuf.component_handle = port->component->handle; - m.u.buffer_from_host.drvbuf.port_handle = port->handle; - m.u.buffer_from_host.drvbuf.client_context = msg_context->handle; - - /* buffer header */ - m.u.buffer_from_host.buffer_header.cmd = 0; - m.u.buffer_from_host.buffer_header.data = - (u32)(unsigned long)buf->buffer; - m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size; - m.u.buffer_from_host.buffer_header.length = 0; /* nothing used yet */ - m.u.buffer_from_host.buffer_header.offset = 0; /* no offset */ - m.u.buffer_from_host.buffer_header.flags = 0; /* no flags */ - m.u.buffer_from_host.buffer_header.pts = MMAL_TIME_UNKNOWN; - m.u.buffer_from_host.buffer_header.dts = MMAL_TIME_UNKNOWN; - - /* clear buffer type specific data */ - memset(&m.u.buffer_from_host.buffer_header_type_specific, 0, - sizeof(m.u.buffer_from_host.buffer_header_type_specific)); - - /* no payload in message */ - m.u.buffer_from_host.payload_in_message = 0; - - vchiq_use_service(instance->vchiq_instance, instance->service_handle); - - ret = vchiq_queue_kernel_message(instance->vchiq_instance, instance->service_handle, &m, - sizeof(struct mmal_msg_header) + - sizeof(m.u.buffer_from_host)); - if (ret) - atomic_dec(&port->buffers_with_vpu); - - vchiq_release_service(instance->vchiq_instance, instance->service_handle); - - return ret; -} - -/* deals with receipt of buffer to host message */ -static void buffer_to_host_cb(struct vchiq_mmal_instance *instance, - struct mmal_msg *msg, u32 msg_len) -{ - struct mmal_msg_context *msg_context; - u32 handle; - - pr_debug("%s: instance:%p msg:%p msg_len:%d\n", - __func__, instance, msg, msg_len); - - if (msg->u.buffer_from_host.drvbuf.magic == MMAL_MAGIC) { - handle = msg->u.buffer_from_host.drvbuf.client_context; - msg_context = lookup_msg_context(instance, handle); - - if (!msg_context) { - pr_err("drvbuf.client_context(%u) is invalid\n", - handle); - return; - } - } else { - pr_err("MMAL_MSG_TYPE_BUFFER_TO_HOST with bad magic\n"); - return; - } - - msg_context->u.bulk.mmal_flags = - msg->u.buffer_from_host.buffer_header.flags; - - if (msg->h.status != MMAL_MSG_STATUS_SUCCESS) { - /* message reception had an error */ - pr_warn("error %d in reply\n", msg->h.status); - - msg_context->u.bulk.status = msg->h.status; - - } else if (msg->u.buffer_from_host.buffer_header.length == 0) { - /* empty buffer */ - if (msg->u.buffer_from_host.buffer_header.flags & - MMAL_BUFFER_HEADER_FLAG_EOS) { - msg_context->u.bulk.status = - bulk_receive(instance, msg, msg_context); - if (msg_context->u.bulk.status == 0) - return; /* successful bulk submission, bulk - * completion will trigger callback - */ - } else { - /* do callback with empty buffer - not EOS though */ - msg_context->u.bulk.status = 0; - msg_context->u.bulk.buffer_used = 0; - } - } else if (msg->u.buffer_from_host.payload_in_message == 0) { - /* data is not in message, queue a bulk receive */ - msg_context->u.bulk.status = - bulk_receive(instance, msg, msg_context); - if (msg_context->u.bulk.status == 0) - return; /* successful bulk submission, bulk - * completion will trigger callback - */ - - /* failed to submit buffer, this will end badly */ - pr_err("error %d on bulk submission\n", - msg_context->u.bulk.status); - - } else if (msg->u.buffer_from_host.payload_in_message <= - MMAL_VC_SHORT_DATA) { - /* data payload within message */ - msg_context->u.bulk.status = inline_receive(instance, msg, - msg_context); - } else { - pr_err("message with invalid short payload\n"); - - /* signal error */ - msg_context->u.bulk.status = -EINVAL; - msg_context->u.bulk.buffer_used = - msg->u.buffer_from_host.payload_in_message; - } - - /* schedule the port callback */ - schedule_work(&msg_context->u.bulk.work); -} - -static void bulk_receive_cb(struct vchiq_mmal_instance *instance, - struct mmal_msg_context *msg_context) -{ - msg_context->u.bulk.status = 0; - - /* schedule the port callback */ - schedule_work(&msg_context->u.bulk.work); -} - -static void bulk_abort_cb(struct vchiq_mmal_instance *instance, - struct mmal_msg_context *msg_context) -{ - pr_err("%s: bulk ABORTED msg_context:%p\n", __func__, msg_context); - - msg_context->u.bulk.status = -EINTR; - - schedule_work(&msg_context->u.bulk.work); -} - -/* incoming event service callback */ -static int mmal_service_callback(struct vchiq_instance *vchiq_instance, - enum vchiq_reason reason, struct vchiq_header *header, - unsigned int handle, void *cb_data, - void __user *cb_userdata) -{ - struct vchiq_mmal_instance *instance = vchiq_get_service_userdata(vchiq_instance, handle); - u32 msg_len; - struct mmal_msg *msg; - struct mmal_msg_context *msg_context; - - if (!instance) { - pr_err("Message callback passed NULL instance\n"); - return 0; - } - - switch (reason) { - case VCHIQ_MESSAGE_AVAILABLE: - msg = (void *)header->data; - msg_len = header->size; - - DBG_DUMP_MSG(msg, msg_len, "<<< reply message"); - - /* handling is different for buffer messages */ - switch (msg->h.type) { - case MMAL_MSG_TYPE_BUFFER_FROM_HOST: - vchiq_release_message(vchiq_instance, handle, header); - break; - - case MMAL_MSG_TYPE_EVENT_TO_HOST: - event_to_host_cb(instance, msg, msg_len); - vchiq_release_message(vchiq_instance, handle, header); - - break; - - case MMAL_MSG_TYPE_BUFFER_TO_HOST: - buffer_to_host_cb(instance, msg, msg_len); - vchiq_release_message(vchiq_instance, handle, header); - break; - - default: - /* messages dependent on header context to complete */ - if (!msg->h.context) { - pr_err("received message context was null!\n"); - vchiq_release_message(vchiq_instance, handle, header); - break; - } - - msg_context = lookup_msg_context(instance, - msg->h.context); - if (!msg_context) { - pr_err("received invalid message context %u!\n", - msg->h.context); - vchiq_release_message(vchiq_instance, handle, header); - break; - } - - /* fill in context values */ - msg_context->u.sync.msg_handle = header; - msg_context->u.sync.msg = msg; - msg_context->u.sync.msg_len = msg_len; - - /* todo: should this check (completion_done() - * == 1) for no one waiting? or do we need a - * flag to tell us the completion has been - * interrupted so we can free the message and - * its context. This probably also solves the - * message arriving after interruption todo - * below - */ - - /* complete message so caller knows it happened */ - complete(&msg_context->u.sync.cmplt); - break; - } - - break; - - case VCHIQ_BULK_RECEIVE_DONE: - bulk_receive_cb(instance, cb_data); - break; - - case VCHIQ_BULK_RECEIVE_ABORTED: - bulk_abort_cb(instance, cb_data); - break; - - case VCHIQ_SERVICE_CLOSED: - /* TODO: consider if this requires action if received when - * driver is not explicitly closing the service - */ - break; - - default: - pr_err("Received unhandled message reason %d\n", reason); - break; - } - - return 0; -} - -static int send_synchronous_mmal_msg(struct vchiq_mmal_instance *instance, - struct mmal_msg *msg, - unsigned int payload_len, - struct mmal_msg **msg_out, - struct vchiq_header **msg_handle) -{ - struct mmal_msg_context *msg_context; - int ret; - unsigned long time_left; - - /* payload size must not cause message to exceed max size */ - if (payload_len > - (MMAL_MSG_MAX_SIZE - sizeof(struct mmal_msg_header))) { - pr_err("payload length %d exceeds max:%d\n", payload_len, - (int)(MMAL_MSG_MAX_SIZE - - sizeof(struct mmal_msg_header))); - return -EINVAL; - } - - msg_context = get_msg_context(instance); - if (IS_ERR(msg_context)) - return PTR_ERR(msg_context); - - init_completion(&msg_context->u.sync.cmplt); - - msg->h.magic = MMAL_MAGIC; - msg->h.context = msg_context->handle; - msg->h.status = 0; - - DBG_DUMP_MSG(msg, (sizeof(struct mmal_msg_header) + payload_len), - ">>> sync message"); - - vchiq_use_service(instance->vchiq_instance, instance->service_handle); - - ret = vchiq_queue_kernel_message(instance->vchiq_instance, instance->service_handle, msg, - sizeof(struct mmal_msg_header) + - payload_len); - - vchiq_release_service(instance->vchiq_instance, instance->service_handle); - - if (ret) { - pr_err("error %d queuing message\n", ret); - release_msg_context(msg_context); - return ret; - } - - time_left = wait_for_completion_timeout(&msg_context->u.sync.cmplt, - SYNC_MSG_TIMEOUT * HZ); - if (time_left == 0) { - pr_err("timed out waiting for sync completion\n"); - ret = -ETIME; - /* todo: what happens if the message arrives after aborting */ - release_msg_context(msg_context); - return ret; - } - - *msg_out = msg_context->u.sync.msg; - *msg_handle = msg_context->u.sync.msg_handle; - release_msg_context(msg_context); - - return 0; -} - -static void dump_port_info(struct vchiq_mmal_port *port) -{ - pr_debug("port handle:0x%x enabled:%d\n", port->handle, port->enabled); - - pr_debug("buffer minimum num:%d size:%d align:%d\n", - port->minimum_buffer.num, - port->minimum_buffer.size, port->minimum_buffer.alignment); - - pr_debug("buffer recommended num:%d size:%d align:%d\n", - port->recommended_buffer.num, - port->recommended_buffer.size, - port->recommended_buffer.alignment); - - pr_debug("buffer current values num:%d size:%d align:%d\n", - port->current_buffer.num, - port->current_buffer.size, port->current_buffer.alignment); - - pr_debug("elementary stream: type:%d encoding:0x%x variant:0x%x\n", - port->format.type, - port->format.encoding, port->format.encoding_variant); - - pr_debug(" bitrate:%d flags:0x%x\n", - port->format.bitrate, port->format.flags); - - if (port->format.type == MMAL_ES_TYPE_VIDEO) { - pr_debug - ("es video format: width:%d height:%d colourspace:0x%x\n", - port->es.video.width, port->es.video.height, - port->es.video.color_space); - - pr_debug(" : crop xywh %d,%d,%d,%d\n", - port->es.video.crop.x, - port->es.video.crop.y, - port->es.video.crop.width, port->es.video.crop.height); - pr_debug(" : framerate %d/%d aspect %d/%d\n", - port->es.video.frame_rate.numerator, - port->es.video.frame_rate.denominator, - port->es.video.par.numerator, port->es.video.par.denominator); - } -} - -static void port_to_mmal_msg(struct vchiq_mmal_port *port, struct mmal_port *p) -{ - /* todo do readonly fields need setting at all? */ - p->type = port->type; - p->index = port->index; - p->index_all = 0; - p->is_enabled = port->enabled; - p->buffer_num_min = port->minimum_buffer.num; - p->buffer_size_min = port->minimum_buffer.size; - p->buffer_alignment_min = port->minimum_buffer.alignment; - p->buffer_num_recommended = port->recommended_buffer.num; - p->buffer_size_recommended = port->recommended_buffer.size; - - /* only three writable fields in a port */ - p->buffer_num = port->current_buffer.num; - p->buffer_size = port->current_buffer.size; - p->userdata = (u32)(unsigned long)port; -} - -static int port_info_set(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port) -{ - int ret; - struct mmal_msg m; - struct mmal_msg *rmsg; - struct vchiq_header *rmsg_handle; - - pr_debug("setting port info port %p\n", port); - if (!port) - return -1; - dump_port_info(port); - - m.h.type = MMAL_MSG_TYPE_PORT_INFO_SET; - - m.u.port_info_set.component_handle = port->component->handle; - m.u.port_info_set.port_type = port->type; - m.u.port_info_set.port_index = port->index; - - port_to_mmal_msg(port, &m.u.port_info_set.port); - - /* elementary stream format setup */ - m.u.port_info_set.format.type = port->format.type; - m.u.port_info_set.format.encoding = port->format.encoding; - m.u.port_info_set.format.encoding_variant = - port->format.encoding_variant; - m.u.port_info_set.format.bitrate = port->format.bitrate; - m.u.port_info_set.format.flags = port->format.flags; - - memcpy(&m.u.port_info_set.es, &port->es, - sizeof(union mmal_es_specific_format)); - - m.u.port_info_set.format.extradata_size = port->format.extradata_size; - memcpy(&m.u.port_info_set.extradata, port->format.extradata, - port->format.extradata_size); - - ret = send_synchronous_mmal_msg(instance, &m, - sizeof(m.u.port_info_set), - &rmsg, &rmsg_handle); - if (ret) - return ret; - - if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_SET) { - /* got an unexpected message type in reply */ - ret = -EINVAL; - goto release_msg; - } - - /* return operation status */ - ret = -rmsg->u.port_info_get_reply.status; - - pr_debug("%s:result:%d component:0x%x port:%d\n", __func__, ret, - port->component->handle, port->handle); - -release_msg: - vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); - - return ret; -} - -/* use port info get message to retrieve port information */ -static int port_info_get(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port) -{ - int ret; - struct mmal_msg m; - struct mmal_msg *rmsg; - struct vchiq_header *rmsg_handle; - - /* port info time */ - m.h.type = MMAL_MSG_TYPE_PORT_INFO_GET; - m.u.port_info_get.component_handle = port->component->handle; - m.u.port_info_get.port_type = port->type; - m.u.port_info_get.index = port->index; - - ret = send_synchronous_mmal_msg(instance, &m, - sizeof(m.u.port_info_get), - &rmsg, &rmsg_handle); - if (ret) - return ret; - - if (rmsg->h.type != MMAL_MSG_TYPE_PORT_INFO_GET) { - /* got an unexpected message type in reply */ - ret = -EINVAL; - goto release_msg; - } - - /* return operation status */ - ret = -rmsg->u.port_info_get_reply.status; - if (ret != MMAL_MSG_STATUS_SUCCESS) - goto release_msg; - - if (rmsg->u.port_info_get_reply.port.is_enabled == 0) - port->enabled = false; - else - port->enabled = true; - - /* copy the values out of the message */ - port->handle = rmsg->u.port_info_get_reply.port_handle; - - /* port type and index cached to use on port info set because - * it does not use a port handle - */ - port->type = rmsg->u.port_info_get_reply.port_type; - port->index = rmsg->u.port_info_get_reply.port_index; - - port->minimum_buffer.num = - rmsg->u.port_info_get_reply.port.buffer_num_min; - port->minimum_buffer.size = - rmsg->u.port_info_get_reply.port.buffer_size_min; - port->minimum_buffer.alignment = - rmsg->u.port_info_get_reply.port.buffer_alignment_min; - - port->recommended_buffer.alignment = - rmsg->u.port_info_get_reply.port.buffer_alignment_min; - port->recommended_buffer.num = - rmsg->u.port_info_get_reply.port.buffer_num_recommended; - - port->current_buffer.num = rmsg->u.port_info_get_reply.port.buffer_num; - port->current_buffer.size = - rmsg->u.port_info_get_reply.port.buffer_size; - - /* stream format */ - port->format.type = rmsg->u.port_info_get_reply.format.type; - port->format.encoding = rmsg->u.port_info_get_reply.format.encoding; - port->format.encoding_variant = - rmsg->u.port_info_get_reply.format.encoding_variant; - port->format.bitrate = rmsg->u.port_info_get_reply.format.bitrate; - port->format.flags = rmsg->u.port_info_get_reply.format.flags; - - /* elementary stream format */ - memcpy(&port->es, - &rmsg->u.port_info_get_reply.es, - sizeof(union mmal_es_specific_format)); - port->format.es = &port->es; - - port->format.extradata_size = - rmsg->u.port_info_get_reply.format.extradata_size; - memcpy(port->format.extradata, - rmsg->u.port_info_get_reply.extradata, - port->format.extradata_size); - - pr_debug("received port info\n"); - dump_port_info(port); - -release_msg: - - pr_debug("%s:result:%d component:0x%x port:%d\n", - __func__, ret, port->component->handle, port->handle); - - vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); - - return ret; -} - -/* create component on vc */ -static int create_component(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *component, - const char *name) -{ - int ret; - struct mmal_msg m; - struct mmal_msg *rmsg; - struct vchiq_header *rmsg_handle; - - /* build component create message */ - m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE; - m.u.component_create.client_component = component->client_component; - strscpy_pad(m.u.component_create.name, name, - sizeof(m.u.component_create.name)); - m.u.component_create.pid = 0; - - ret = send_synchronous_mmal_msg(instance, &m, - sizeof(m.u.component_create), - &rmsg, &rmsg_handle); - if (ret) - return ret; - - if (rmsg->h.type != m.h.type) { - /* got an unexpected message type in reply */ - ret = -EINVAL; - goto release_msg; - } - - ret = -rmsg->u.component_create_reply.status; - if (ret != MMAL_MSG_STATUS_SUCCESS) - goto release_msg; - - /* a valid component response received */ - component->handle = rmsg->u.component_create_reply.component_handle; - component->inputs = rmsg->u.component_create_reply.input_num; - component->outputs = rmsg->u.component_create_reply.output_num; - component->clocks = rmsg->u.component_create_reply.clock_num; - - pr_debug("Component handle:0x%x in:%d out:%d clock:%d\n", - component->handle, - component->inputs, component->outputs, component->clocks); - -release_msg: - vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); - - return ret; -} - -/* destroys a component on vc */ -static int destroy_component(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *component) -{ - int ret; - struct mmal_msg m; - struct mmal_msg *rmsg; - struct vchiq_header *rmsg_handle; - - m.h.type = MMAL_MSG_TYPE_COMPONENT_DESTROY; - m.u.component_destroy.component_handle = component->handle; - - ret = send_synchronous_mmal_msg(instance, &m, - sizeof(m.u.component_destroy), - &rmsg, &rmsg_handle); - if (ret) - return ret; - - if (rmsg->h.type != m.h.type) { - /* got an unexpected message type in reply */ - ret = -EINVAL; - goto release_msg; - } - - ret = -rmsg->u.component_destroy_reply.status; - -release_msg: - - vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); - - return ret; -} - -/* enable a component on vc */ -static int enable_component(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *component) -{ - int ret; - struct mmal_msg m; - struct mmal_msg *rmsg; - struct vchiq_header *rmsg_handle; - - m.h.type = MMAL_MSG_TYPE_COMPONENT_ENABLE; - m.u.component_enable.component_handle = component->handle; - - ret = send_synchronous_mmal_msg(instance, &m, - sizeof(m.u.component_enable), - &rmsg, &rmsg_handle); - if (ret) - return ret; - - if (rmsg->h.type != m.h.type) { - /* got an unexpected message type in reply */ - ret = -EINVAL; - goto release_msg; - } - - ret = -rmsg->u.component_enable_reply.status; - -release_msg: - vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); - - return ret; -} - -/* disable a component on vc */ -static int disable_component(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *component) -{ - int ret; - struct mmal_msg m; - struct mmal_msg *rmsg; - struct vchiq_header *rmsg_handle; - - m.h.type = MMAL_MSG_TYPE_COMPONENT_DISABLE; - m.u.component_disable.component_handle = component->handle; - - ret = send_synchronous_mmal_msg(instance, &m, - sizeof(m.u.component_disable), - &rmsg, &rmsg_handle); - if (ret) - return ret; - - if (rmsg->h.type != m.h.type) { - /* got an unexpected message type in reply */ - ret = -EINVAL; - goto release_msg; - } - - ret = -rmsg->u.component_disable_reply.status; - -release_msg: - - vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); - - return ret; -} - -/* get version of mmal implementation */ -static int get_version(struct vchiq_mmal_instance *instance, - u32 *major_out, u32 *minor_out) -{ - int ret; - struct mmal_msg m; - struct mmal_msg *rmsg; - struct vchiq_header *rmsg_handle; - - m.h.type = MMAL_MSG_TYPE_GET_VERSION; - - ret = send_synchronous_mmal_msg(instance, &m, - sizeof(m.u.version), - &rmsg, &rmsg_handle); - if (ret) - return ret; - - if (rmsg->h.type != m.h.type) { - /* got an unexpected message type in reply */ - ret = -EINVAL; - goto release_msg; - } - - *major_out = rmsg->u.version.major; - *minor_out = rmsg->u.version.minor; - -release_msg: - vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); - - return ret; -} - -/* do a port action with a port as a parameter */ -static int port_action_port(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - enum mmal_msg_port_action_type action_type) -{ - int ret; - struct mmal_msg m; - struct mmal_msg *rmsg; - struct vchiq_header *rmsg_handle; - - m.h.type = MMAL_MSG_TYPE_PORT_ACTION; - m.u.port_action_port.component_handle = port->component->handle; - m.u.port_action_port.port_handle = port->handle; - m.u.port_action_port.action = action_type; - - port_to_mmal_msg(port, &m.u.port_action_port.port); - - ret = send_synchronous_mmal_msg(instance, &m, - sizeof(m.u.port_action_port), - &rmsg, &rmsg_handle); - if (ret) - return ret; - - if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) { - /* got an unexpected message type in reply */ - ret = -EINVAL; - goto release_msg; - } - - ret = -rmsg->u.port_action_reply.status; - - pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d)\n", - __func__, - ret, port->component->handle, port->handle, - port_action_type_names[action_type], action_type); - -release_msg: - vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); - - return ret; -} - -/* do a port action with handles as parameters */ -static int port_action_handle(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - enum mmal_msg_port_action_type action_type, - u32 connect_component_handle, - u32 connect_port_handle) -{ - int ret; - struct mmal_msg m; - struct mmal_msg *rmsg; - struct vchiq_header *rmsg_handle; - - m.h.type = MMAL_MSG_TYPE_PORT_ACTION; - - m.u.port_action_handle.component_handle = port->component->handle; - m.u.port_action_handle.port_handle = port->handle; - m.u.port_action_handle.action = action_type; - - m.u.port_action_handle.connect_component_handle = - connect_component_handle; - m.u.port_action_handle.connect_port_handle = connect_port_handle; - - ret = send_synchronous_mmal_msg(instance, &m, - sizeof(m.u.port_action_handle), - &rmsg, &rmsg_handle); - if (ret) - return ret; - - if (rmsg->h.type != MMAL_MSG_TYPE_PORT_ACTION) { - /* got an unexpected message type in reply */ - ret = -EINVAL; - goto release_msg; - } - - ret = -rmsg->u.port_action_reply.status; - - pr_debug("%s:result:%d component:0x%x port:%d action:%s(%d) connect component:0x%x connect port:%d\n", - __func__, - ret, port->component->handle, port->handle, - port_action_type_names[action_type], - action_type, connect_component_handle, connect_port_handle); - -release_msg: - vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); - - return ret; -} - -static int port_parameter_set(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - u32 parameter_id, void *value, u32 value_size) -{ - int ret; - struct mmal_msg m; - struct mmal_msg *rmsg; - struct vchiq_header *rmsg_handle; - - m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_SET; - - m.u.port_parameter_set.component_handle = port->component->handle; - m.u.port_parameter_set.port_handle = port->handle; - m.u.port_parameter_set.id = parameter_id; - m.u.port_parameter_set.size = (2 * sizeof(u32)) + value_size; - memcpy(&m.u.port_parameter_set.value, value, value_size); - - ret = send_synchronous_mmal_msg(instance, &m, - (4 * sizeof(u32)) + value_size, - &rmsg, &rmsg_handle); - if (ret) - return ret; - - if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_SET) { - /* got an unexpected message type in reply */ - ret = -EINVAL; - goto release_msg; - } - - ret = -rmsg->u.port_parameter_set_reply.status; - - pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", - __func__, - ret, port->component->handle, port->handle, parameter_id); - -release_msg: - vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); - - return ret; -} - -static int port_parameter_get(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - u32 parameter_id, void *value, u32 *value_size) -{ - int ret; - struct mmal_msg m; - struct mmal_msg *rmsg; - struct vchiq_header *rmsg_handle; - - m.h.type = MMAL_MSG_TYPE_PORT_PARAMETER_GET; - - m.u.port_parameter_get.component_handle = port->component->handle; - m.u.port_parameter_get.port_handle = port->handle; - m.u.port_parameter_get.id = parameter_id; - m.u.port_parameter_get.size = (2 * sizeof(u32)) + *value_size; - - ret = send_synchronous_mmal_msg(instance, &m, - sizeof(struct - mmal_msg_port_parameter_get), - &rmsg, &rmsg_handle); - if (ret) - return ret; - - if (rmsg->h.type != MMAL_MSG_TYPE_PORT_PARAMETER_GET) { - /* got an unexpected message type in reply */ - pr_err("Incorrect reply type %d\n", rmsg->h.type); - ret = -EINVAL; - goto release_msg; - } - - ret = rmsg->u.port_parameter_get_reply.status; - - /* port_parameter_get_reply.size includes the header, - * whilst *value_size doesn't. - */ - rmsg->u.port_parameter_get_reply.size -= (2 * sizeof(u32)); - - if (ret || rmsg->u.port_parameter_get_reply.size > *value_size) { - /* Copy only as much as we have space for - * but report true size of parameter - */ - memcpy(value, &rmsg->u.port_parameter_get_reply.value, - *value_size); - } else { - memcpy(value, &rmsg->u.port_parameter_get_reply.value, - rmsg->u.port_parameter_get_reply.size); - } - /* Always report the size of the returned parameter to the caller */ - *value_size = rmsg->u.port_parameter_get_reply.size; - - pr_debug("%s:result:%d component:0x%x port:%d parameter:%d\n", __func__, - ret, port->component->handle, port->handle, parameter_id); - -release_msg: - vchiq_release_message(instance->vchiq_instance, instance->service_handle, rmsg_handle); - - return ret; -} - -/* disables a port and drains buffers from it */ -static int port_disable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port) -{ - int ret; - struct list_head *q, *buf_head; - unsigned long flags = 0; - - if (!port->enabled) - return 0; - - port->enabled = false; - - ret = port_action_port(instance, port, - MMAL_MSG_PORT_ACTION_TYPE_DISABLE); - if (ret == 0) { - /* - * Drain all queued buffers on port. This should only - * apply to buffers that have been queued before the port - * has been enabled. If the port has been enabled and buffers - * passed, then the buffers should have been removed from this - * list, and we should get the relevant callbacks via VCHIQ - * to release the buffers. - */ - spin_lock_irqsave(&port->slock, flags); - - list_for_each_safe(buf_head, q, &port->buffers) { - struct mmal_buffer *mmalbuf; - - mmalbuf = list_entry(buf_head, struct mmal_buffer, - list); - list_del(buf_head); - if (port->buffer_cb) { - mmalbuf->length = 0; - mmalbuf->mmal_flags = 0; - mmalbuf->dts = MMAL_TIME_UNKNOWN; - mmalbuf->pts = MMAL_TIME_UNKNOWN; - port->buffer_cb(instance, - port, 0, mmalbuf); - } - } - - spin_unlock_irqrestore(&port->slock, flags); - - ret = port_info_get(instance, port); - } - - return ret; -} - -/* enable a port */ -static int port_enable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port) -{ - unsigned int hdr_count; - struct list_head *q, *buf_head; - int ret; - - if (port->enabled) - return 0; - - ret = port_action_port(instance, port, - MMAL_MSG_PORT_ACTION_TYPE_ENABLE); - if (ret) - goto done; - - port->enabled = true; - - if (port->buffer_cb) { - /* send buffer headers to videocore */ - hdr_count = 1; - list_for_each_safe(buf_head, q, &port->buffers) { - struct mmal_buffer *mmalbuf; - - mmalbuf = list_entry(buf_head, struct mmal_buffer, - list); - ret = buffer_from_host(instance, port, mmalbuf); - if (ret) - goto done; - - list_del(buf_head); - hdr_count++; - if (hdr_count > port->current_buffer.num) - break; - } - } - - ret = port_info_get(instance, port); - -done: - return ret; -} - -/* ------------------------------------------------------------------ - * Exported API - *------------------------------------------------------------------ - */ - -int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - ret = port_info_set(instance, port); - if (ret) - goto release_unlock; - - /* read what has actually been set */ - ret = port_info_get(instance, port); - -release_unlock: - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_port_set_format); - -int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - u32 parameter, void *value, u32 value_size) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - ret = port_parameter_set(instance, port, parameter, value, value_size); - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set); - -int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - u32 parameter, void *value, u32 *value_size) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - ret = port_parameter_get(instance, port, parameter, value, value_size); - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_get); - -/* enable a port - * - * enables a port and queues buffers for satisfying callbacks if we - * provide a callback handler - */ -int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - vchiq_mmal_buffer_cb buffer_cb) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - /* already enabled - noop */ - if (port->enabled) { - ret = 0; - goto unlock; - } - - port->buffer_cb = buffer_cb; - - ret = port_enable(instance, port); - -unlock: - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_port_enable); - -int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - if (!port->enabled) { - mutex_unlock(&instance->vchiq_mutex); - return 0; - } - - ret = port_disable(instance, port); - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_port_disable); - -/* ports will be connected in a tunneled manner so data buffers - * are not handled by client. - */ -int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *src, - struct vchiq_mmal_port *dst) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - /* disconnect ports if connected */ - if (src->connected) { - ret = port_disable(instance, src); - if (ret) { - pr_err("failed disabling src port(%d)\n", ret); - goto release_unlock; - } - - /* do not need to disable the destination port as they - * are connected and it is done automatically - */ - - ret = port_action_handle(instance, src, - MMAL_MSG_PORT_ACTION_TYPE_DISCONNECT, - src->connected->component->handle, - src->connected->handle); - if (ret < 0) { - pr_err("failed disconnecting src port\n"); - goto release_unlock; - } - src->connected->enabled = false; - src->connected = NULL; - } - - if (!dst) { - /* do not make new connection */ - ret = 0; - pr_debug("not making new connection\n"); - goto release_unlock; - } - - /* copy src port format to dst */ - dst->format.encoding = src->format.encoding; - dst->es.video.width = src->es.video.width; - dst->es.video.height = src->es.video.height; - dst->es.video.crop.x = src->es.video.crop.x; - dst->es.video.crop.y = src->es.video.crop.y; - dst->es.video.crop.width = src->es.video.crop.width; - dst->es.video.crop.height = src->es.video.crop.height; - dst->es.video.frame_rate.numerator = src->es.video.frame_rate.numerator; - dst->es.video.frame_rate.denominator = src->es.video.frame_rate.denominator; - - /* set new format */ - ret = port_info_set(instance, dst); - if (ret) { - pr_debug("setting port info failed\n"); - goto release_unlock; - } - - /* read what has actually been set */ - ret = port_info_get(instance, dst); - if (ret) { - pr_debug("read back port info failed\n"); - goto release_unlock; - } - - /* connect two ports together */ - ret = port_action_handle(instance, src, - MMAL_MSG_PORT_ACTION_TYPE_CONNECT, - dst->component->handle, dst->handle); - if (ret < 0) { - pr_debug("connecting port %d:%d to %d:%d failed\n", - src->component->handle, src->handle, - dst->component->handle, dst->handle); - goto release_unlock; - } - src->connected = dst; - -release_unlock: - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_port_connect_tunnel); - -int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - struct mmal_buffer *buffer) -{ - unsigned long flags = 0; - int ret; - - ret = buffer_from_host(instance, port, buffer); - if (ret == -EINVAL) { - /* Port is disabled. Queue for when it is enabled. */ - spin_lock_irqsave(&port->slock, flags); - list_add_tail(&buffer->list, &port->buffers); - spin_unlock_irqrestore(&port->slock, flags); - } - - return 0; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_submit_buffer); - -int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance, - struct mmal_buffer *buf) -{ - struct mmal_msg_context *msg_context = get_msg_context(instance); - - if (IS_ERR(msg_context)) - return (PTR_ERR(msg_context)); - - buf->msg_context = msg_context; - return 0; -} -EXPORT_SYMBOL_GPL(mmal_vchi_buffer_init); - -int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf) -{ - struct mmal_msg_context *msg_context = buf->msg_context; - - if (msg_context) - release_msg_context(msg_context); - buf->msg_context = NULL; - - return 0; -} -EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup); - -/* Initialise a mmal component and its ports - * - */ -int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance, - const char *name, - struct vchiq_mmal_component **component_out) -{ - int ret; - int idx; /* port index */ - struct vchiq_mmal_component *component = NULL; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - for (idx = 0; idx < VCHIQ_MMAL_MAX_COMPONENTS; idx++) { - if (!instance->component[idx].in_use) { - component = &instance->component[idx]; - component->in_use = true; - break; - } - } - - if (!component) { - ret = -EINVAL; /* todo is this correct error? */ - goto unlock; - } - - /* We need a handle to reference back to our component structure. - * Use the array index in instance->component rather than rolling - * another IDR. - */ - component->client_component = idx; - - ret = create_component(instance, component, name); - if (ret < 0) { - pr_err("%s: failed to create component %d (Not enough GPU mem?)\n", - __func__, ret); - goto unlock; - } - - /* ports info needs gathering */ - component->control.type = MMAL_PORT_TYPE_CONTROL; - component->control.index = 0; - component->control.component = component; - spin_lock_init(&component->control.slock); - INIT_LIST_HEAD(&component->control.buffers); - ret = port_info_get(instance, &component->control); - if (ret < 0) - goto release_component; - - for (idx = 0; idx < component->inputs; idx++) { - component->input[idx].type = MMAL_PORT_TYPE_INPUT; - component->input[idx].index = idx; - component->input[idx].component = component; - spin_lock_init(&component->input[idx].slock); - INIT_LIST_HEAD(&component->input[idx].buffers); - ret = port_info_get(instance, &component->input[idx]); - if (ret < 0) - goto release_component; - } - - for (idx = 0; idx < component->outputs; idx++) { - component->output[idx].type = MMAL_PORT_TYPE_OUTPUT; - component->output[idx].index = idx; - component->output[idx].component = component; - spin_lock_init(&component->output[idx].slock); - INIT_LIST_HEAD(&component->output[idx].buffers); - ret = port_info_get(instance, &component->output[idx]); - if (ret < 0) - goto release_component; - } - - for (idx = 0; idx < component->clocks; idx++) { - component->clock[idx].type = MMAL_PORT_TYPE_CLOCK; - component->clock[idx].index = idx; - component->clock[idx].component = component; - spin_lock_init(&component->clock[idx].slock); - INIT_LIST_HEAD(&component->clock[idx].buffers); - ret = port_info_get(instance, &component->clock[idx]); - if (ret < 0) - goto release_component; - } - - *component_out = component; - - mutex_unlock(&instance->vchiq_mutex); - - return 0; - -release_component: - destroy_component(instance, component); -unlock: - if (component) - component->in_use = false; - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_component_init); - -/* - * cause a mmal component to be destroyed - */ -int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *component) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - if (component->enabled) - ret = disable_component(instance, component); - - ret = destroy_component(instance, component); - - component->in_use = false; - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_component_finalise); - -/* - * cause a mmal component to be enabled - */ -int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *component) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - if (component->enabled) { - mutex_unlock(&instance->vchiq_mutex); - return 0; - } - - ret = enable_component(instance, component); - if (ret == 0) - component->enabled = true; - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_component_enable); - -/* - * cause a mmal component to be enabled - */ -int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *component) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - if (!component->enabled) { - mutex_unlock(&instance->vchiq_mutex); - return 0; - } - - ret = disable_component(instance, component); - if (ret == 0) - component->enabled = false; - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_component_disable); - -int vchiq_mmal_version(struct vchiq_mmal_instance *instance, - u32 *major_out, u32 *minor_out) -{ - int ret; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - ret = get_version(instance, major_out, minor_out); - - mutex_unlock(&instance->vchiq_mutex); - - return ret; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_version); - -int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance) -{ - int status = 0; - - if (!instance) - return -EINVAL; - - if (mutex_lock_interruptible(&instance->vchiq_mutex)) - return -EINTR; - - vchiq_use_service(instance->vchiq_instance, instance->service_handle); - - status = vchiq_close_service(instance->vchiq_instance, instance->service_handle); - if (status != 0) - pr_err("mmal-vchiq: VCHIQ close failed\n"); - - mutex_unlock(&instance->vchiq_mutex); - - vchiq_shutdown(instance->vchiq_instance); - destroy_workqueue(instance->bulk_wq); - - idr_destroy(&instance->context_map); - - kfree(instance); - - return status; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_finalise); - -int vchiq_mmal_init(struct device *dev, struct vchiq_mmal_instance **out_instance) -{ - int status; - int err = -ENODEV; - struct vchiq_mmal_instance *instance; - struct vchiq_instance *vchiq_instance; - struct vchiq_service_params_kernel params = { - .version = VC_MMAL_VER, - .version_min = VC_MMAL_MIN_VER, - .fourcc = VCHIQ_MAKE_FOURCC('m', 'm', 'a', 'l'), - .callback = mmal_service_callback, - .userdata = NULL, - }; - struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(dev->parent); - - /* compile time checks to ensure structure size as they are - * directly (de)serialised from memory. - */ - - /* ensure the header structure has packed to the correct size */ - BUILD_BUG_ON(sizeof(struct mmal_msg_header) != 24); - - /* ensure message structure does not exceed maximum length */ - BUILD_BUG_ON(sizeof(struct mmal_msg) > MMAL_MSG_MAX_SIZE); - - /* mmal port struct is correct size */ - BUILD_BUG_ON(sizeof(struct mmal_port) != 64); - - /* create a vchi instance */ - status = vchiq_initialise(&mgmt->state, &vchiq_instance); - if (status) { - pr_err("Failed to initialise VCHI instance (status=%d)\n", - status); - return -EIO; - } - - status = vchiq_connect(vchiq_instance); - if (status) { - pr_err("Failed to connect VCHI instance (status=%d)\n", status); - err = -EIO; - goto err_shutdown_vchiq; - } - - instance = kzalloc(sizeof(*instance), GFP_KERNEL); - - if (!instance) { - err = -ENOMEM; - goto err_shutdown_vchiq; - } - - mutex_init(&instance->vchiq_mutex); - - instance->vchiq_instance = vchiq_instance; - - mutex_init(&instance->context_map_lock); - idr_init_base(&instance->context_map, 1); - - params.userdata = instance; - - instance->bulk_wq = alloc_ordered_workqueue("mmal-vchiq", - WQ_MEM_RECLAIM); - if (!instance->bulk_wq) - goto err_free; - - status = vchiq_open_service(vchiq_instance, ¶ms, - &instance->service_handle); - if (status) { - pr_err("Failed to open VCHI service connection (status=%d)\n", - status); - goto err_close_services; - } - - vchiq_release_service(instance->vchiq_instance, instance->service_handle); - - *out_instance = instance; - - return 0; - -err_close_services: - vchiq_close_service(instance->vchiq_instance, instance->service_handle); - destroy_workqueue(instance->bulk_wq); -err_free: - kfree(instance); -err_shutdown_vchiq: - vchiq_shutdown(vchiq_instance); - return err; -} -EXPORT_SYMBOL_GPL(vchiq_mmal_init); - -MODULE_DESCRIPTION("BCM2835 MMAL VCHIQ interface"); -MODULE_AUTHOR("Dave Stevenson, <dave.stevenson@raspberrypi.org>"); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h deleted file mode 100644 index 8c3959f6f97f..000000000000 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h +++ /dev/null @@ -1,162 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Broadcom BCM2835 V4L2 driver - * - * Copyright © 2013 Raspberry Pi (Trading) Ltd. - * - * Authors: Vincent Sanders @ Collabora - * Dave Stevenson @ Broadcom - * (now dave.stevenson@raspberrypi.org) - * Simon Mellor @ Broadcom - * Luke Diamand @ Broadcom - * - * MMAL interface to VCHIQ message passing - */ - -#ifndef MMAL_VCHIQ_H -#define MMAL_VCHIQ_H - -#include "mmal-common.h" -#include "mmal-msg-format.h" - -#define MAX_PORT_COUNT 4 - -/* Maximum size of the format extradata. */ -#define MMAL_FORMAT_EXTRADATA_MAX_SIZE 128 - -struct vchiq_mmal_instance; -struct device; - -enum vchiq_mmal_es_type { - MMAL_ES_TYPE_UNKNOWN, /**< Unknown elementary stream type */ - MMAL_ES_TYPE_CONTROL, /**< Elementary stream of control commands */ - MMAL_ES_TYPE_AUDIO, /**< Audio elementary stream */ - MMAL_ES_TYPE_VIDEO, /**< Video elementary stream */ - MMAL_ES_TYPE_SUBPICTURE /**< Sub-picture elementary stream */ -}; - -struct vchiq_mmal_port_buffer { - unsigned int num; /* number of buffers */ - u32 size; /* size of buffers */ - u32 alignment; /* alignment of buffers */ -}; - -struct vchiq_mmal_port; - -typedef void (*vchiq_mmal_buffer_cb)(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - int status, struct mmal_buffer *buffer); - -struct vchiq_mmal_port { - bool enabled; - u32 handle; - u32 type; /* port type, cached to use on port info set */ - u32 index; /* port index, cached to use on port info set */ - - /* component port belongs to, allows simple deref */ - struct vchiq_mmal_component *component; - - struct vchiq_mmal_port *connected; /* port connected to */ - - /* buffer info */ - struct vchiq_mmal_port_buffer minimum_buffer; - struct vchiq_mmal_port_buffer recommended_buffer; - struct vchiq_mmal_port_buffer current_buffer; - - /* stream format */ - struct mmal_es_format_local format; - /* elementary stream format */ - union mmal_es_specific_format es; - - /* data buffers to fill */ - struct list_head buffers; - /* lock to serialise adding and removing buffers from list */ - spinlock_t slock; - - /* Count of buffers the VPU has yet to return */ - atomic_t buffers_with_vpu; - /* callback on buffer completion */ - vchiq_mmal_buffer_cb buffer_cb; - /* callback context */ - void *cb_ctx; -}; - -struct vchiq_mmal_component { - bool in_use; - bool enabled; - u32 handle; /* VideoCore handle for component */ - u32 inputs; /* Number of input ports */ - u32 outputs; /* Number of output ports */ - u32 clocks; /* Number of clock ports */ - struct vchiq_mmal_port control; /* control port */ - struct vchiq_mmal_port input[MAX_PORT_COUNT]; /* input ports */ - struct vchiq_mmal_port output[MAX_PORT_COUNT]; /* output ports */ - struct vchiq_mmal_port clock[MAX_PORT_COUNT]; /* clock ports */ - u32 client_component; /* Used to ref back to client struct */ -}; - -int vchiq_mmal_init(struct device *dev, struct vchiq_mmal_instance **out_instance); -int vchiq_mmal_finalise(struct vchiq_mmal_instance *instance); - -/* Initialise a mmal component and its ports - * - */ -int vchiq_mmal_component_init(struct vchiq_mmal_instance *instance, - const char *name, struct vchiq_mmal_component **component_out); - -int vchiq_mmal_component_finalise(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *component); - -int vchiq_mmal_component_enable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *component); - -int vchiq_mmal_component_disable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_component *component); - -/* enable a mmal port - * - * enables a port and, if a buffer callback provided, enqueues buffer - * headers as appropriate for the port. - */ -int vchiq_mmal_port_enable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - vchiq_mmal_buffer_cb buffer_cb); - -/* disable a port - * - * disable a port will dequeue any pending buffers - */ -int vchiq_mmal_port_disable(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port); - -int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - u32 parameter, - void *value, - u32 value_size); - -int vchiq_mmal_port_parameter_get(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - u32 parameter, - void *value, - u32 *value_size); - -int vchiq_mmal_port_set_format(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port); - -int vchiq_mmal_port_connect_tunnel(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *src, - struct vchiq_mmal_port *dst); - -int vchiq_mmal_version(struct vchiq_mmal_instance *instance, - u32 *major_out, - u32 *minor_out); - -int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance, - struct vchiq_mmal_port *port, - struct mmal_buffer *buf); - -int mmal_vchi_buffer_init(struct vchiq_mmal_instance *instance, - struct mmal_buffer *buf); -int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf); -#endif /* MMAL_VCHIQ_H */ |
