[PATCH 19/38] staging: comedi: ni_pcidio: use request_firmware()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The PCI-6534 needs three firmware files loading to work with the driver.
That is currently done by passing the firmware data using the
`COMEDI_DEVCONFIG` ioctl that uses the comedi `attach()` hook in the
driver.  This doesn't work for auto-configured PCI devices (which also
currently use the `attach()` hook in this driver, but doesn't have the
firmware-loading options set in the `struct comedi_devconfig *`
parameter).

Change the driver to request the firmware files using
`request_firmware()`, ignoring any firmware-loading options set in the
`struct comedi_devconfig`.

The PCI-6534 has a main FPGA which needs to be loaded first, and two
"scarabs".  Scarab A is loaded with firmware to support digital input
mode, and scarab B is loaded with firmware to support digital output
mode.

I don't think the order of loading the scarab firmwares matters as long
as they are loaded with the correct firmware files.  This update loads
scarab B first, whereas the original code loaded scarab A first.  The
firmware files are loaded in the following order:

A) main FPGA: "ni6534a.bin" (FW_PCI_6534_MAIN)
B) scarab B: "niscrb02.bin" (FW_PCI_6534_SCARAB_DO)
C) scarab A: "niscrb01.bin" (FW_PCI_6534_SCARAB_DI)

The required firmware files can be found in the
"comedi-nonfree-firmware" tar-ball at
<http://www.comedi.org/download/comedi-nonfree-firmware-2007.06.22.tar.gz>.

Signed-off-by: Ian Abbott <abbotti@xxxxxxxxx>
---
 drivers/staging/comedi/drivers/ni_pcidio.c | 61 ++++++++++++++++++------------
 1 file changed, 36 insertions(+), 25 deletions(-)

diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index 4f76daf..a655ab9 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -57,6 +57,7 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org
 
 #include <linux/interrupt.h>
 #include <linux/sched.h>
+#include <linux/firmware.h>
 #include "../comedidev.h"
 
 #include "mite.h"
@@ -230,6 +231,14 @@ static inline unsigned secondary_DMAChannel_bits(unsigned channel)
 #define Protocol_Register_8		88	/* 32 bit */
 #define StartDelay			Protocol_Register_8
 
+/* Firmware files for PCI-6524 */
+#define FW_PCI_6534_MAIN		"ni6534a.bin"
+#define FW_PCI_6534_SCARAB_DI		"niscrb01.bin"
+#define FW_PCI_6534_SCARAB_DO		"niscrb02.bin"
+MODULE_FIRMWARE(FW_PCI_6534_MAIN);
+MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DI);
+MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DO);
+
 enum pci_6534_firmware_registers {	/* 16 bit */
 	Firmware_Control_Register = 0x100,
 	Firmware_Status_Register = 0x104,
@@ -977,10 +986,12 @@ static int ni_pcidio_change(struct comedi_device *dev,
 }
 
 static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
-			      u8 *data, int data_len)
+			      const u8 *data, size_t data_len)
 {
 	static const int timeout = 1000;
-	int i, j;
+	int i;
+	size_t j;
+
 	writew(0x80 | fpga_index,
 	       devpriv->mite->daq_io_addr + Firmware_Control_Register);
 	writew(0xc0 | fpga_index,
@@ -1062,34 +1073,34 @@ static void pci_6534_init_main_fpga(struct comedi_device *dev)
 	writel(0, devpriv->mite->daq_io_addr + FPGA_SCBMS_Counter_Register);
 }
 
-static int pci_6534_upload_firmware(struct comedi_device *dev, int options[])
+static int pci_6534_upload_firmware(struct comedi_device *dev)
 {
 	int ret;
-	void *main_fpga_data, *scarab_a_data, *scarab_b_data;
-	int main_fpga_data_len, scarab_a_data_len, scarab_b_data_len;
+	const struct firmware *fw;
+	static const char *const fw_file[3] = {
+		FW_PCI_6534_SCARAB_DI,	/* loaded into scarab A for DI */
+		FW_PCI_6534_SCARAB_DO,	/* loaded into scarab B for DO */
+		FW_PCI_6534_MAIN,	/* loaded into main FPGA */
+	};
+	int n;
 
-	if (options[COMEDI_DEVCONF_AUX_DATA_LENGTH] == 0)
-		return 0;
 	ret = pci_6534_reset_fpgas(dev);
 	if (ret < 0)
 		return ret;
-	main_fpga_data = comedi_aux_data(options, 0);
-	main_fpga_data_len = options[COMEDI_DEVCONF_AUX_DATA0_LENGTH];
-	ret = pci_6534_load_fpga(dev, 2, main_fpga_data, main_fpga_data_len);
-	if (ret < 0)
-		return ret;
-	pci_6534_init_main_fpga(dev);
-	scarab_a_data = comedi_aux_data(options, 1);
-	scarab_a_data_len = options[COMEDI_DEVCONF_AUX_DATA1_LENGTH];
-	ret = pci_6534_load_fpga(dev, 0, scarab_a_data, scarab_a_data_len);
-	if (ret < 0)
-		return ret;
-	scarab_b_data = comedi_aux_data(options, 2);
-	scarab_b_data_len = options[COMEDI_DEVCONF_AUX_DATA2_LENGTH];
-	ret = pci_6534_load_fpga(dev, 1, scarab_b_data, scarab_b_data_len);
-	if (ret < 0)
-		return ret;
-	return 0;
+	/* load main FPGA first, then the two scarabs */
+	for (n = 2; n >= 0; n--) {
+		ret = request_firmware(&fw, fw_file[n],
+				       &devpriv->mite->pcidev->dev);
+		if (ret == 0) {
+			ret = pci_6534_load_fpga(dev, n, fw->data, fw->size);
+			if (ret == 0 && n == 2)
+				pci_6534_init_main_fpga(dev);
+			release_firmware(fw);
+		}
+		if (ret < 0)
+			break;
+	}
+	return ret;
 }
 
 static int nidio_find_device(struct comedi_device *dev, int bus, int slot)
@@ -1147,7 +1158,7 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	dev->board_name = this_board->name;
 	irq = mite_irq(devpriv->mite);
 	if (this_board->uses_firmware) {
-		ret = pci_6534_upload_firmware(dev, it->options);
+		ret = pci_6534_upload_firmware(dev);
 		if (ret < 0)
 			return ret;
 	}
-- 
1.7.12

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux