summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/isci/firmware')
-rw-r--r--drivers/scsi/isci/firmware/Makefile19
-rw-r--r--drivers/scsi/isci/firmware/README36
-rw-r--r--drivers/scsi/isci/firmware/create_fw.c177
3 files changed, 232 insertions, 0 deletions
diff --git a/drivers/scsi/isci/firmware/Makefile b/drivers/scsi/isci/firmware/Makefile
new file mode 100644
index 00000000000..5f54461cabc
--- /dev/null
+++ b/drivers/scsi/isci/firmware/Makefile
@@ -0,0 +1,19 @@
+# Makefile for create_fw
+#
+CC=gcc
+CFLAGS=-c -Wall -O2 -g
+LDFLAGS=
+SOURCES=create_fw.c
+OBJECTS=$(SOURCES:.cpp=.o)
+EXECUTABLE=create_fw
+
+all: $(SOURCES) $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+ $(CC) $(LDFLAGS) $(OBJECTS) -o $@
+
+.c.o:
+ $(CC) $(CFLAGS) $< -O $@
+
+clean:
+ rm -f *.o $(EXECUTABLE)
diff --git a/drivers/scsi/isci/firmware/README b/drivers/scsi/isci/firmware/README
new file mode 100644
index 00000000000..cf7e4286e89
--- /dev/null
+++ b/drivers/scsi/isci/firmware/README
@@ -0,0 +1,36 @@
+This defines the temporary binary blow we are to pass to the SCU
+driver to emulate the binary firmware that we will eventually be
+able to access via NVRAM on the SCU controller.
+
+The current size of the binary blob is expected to be 149 bytes or larger
+
+Header Types:
+0x1: Phy Masks
+0x2: Phy Gens
+0x3: SAS Addrs
+0xff: End of Data
+
+ID string - u8[12]: "#SCU MAGIC#\0"
+Version - u8: 1
+SubVersion - u8: 0
+
+Header Type - u8: 0x1
+Size - u8: 8
+Phy Mask - u32[8]
+
+Header Type - u8: 0x2
+Size - u8: 8
+Phy Gen - u32[8]
+
+Header Type - u8: 0x3
+Size - u8: 8
+Sas Addr - u64[8]
+
+Header Type - u8: 0xf
+
+
+==============================================================================
+
+Place isci_firmware.bin in /lib/firmware
+Be sure to recreate the initramfs image to include the firmware.
+
diff --git a/drivers/scsi/isci/firmware/create_fw.c b/drivers/scsi/isci/firmware/create_fw.c
new file mode 100644
index 00000000000..442caac9675
--- /dev/null
+++ b/drivers/scsi/isci/firmware/create_fw.c
@@ -0,0 +1,177 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+char blob_name[] = "isci_firmware.bin";
+char id[] = "#SCU MAGIC#";
+unsigned char version = 1;
+unsigned char sub_version = 0;
+
+
+/*
+ * For all defined arrays:
+ * elements 0-3 are for SCU0, ports 0-3
+ * elements 4-7 are for SCU1, ports 0-3
+ *
+ * valid configurations for one SCU are:
+ * P0 P1 P2 P3
+ * ----------------
+ * 0xF,0x0,0x0,0x0 # 1 x4 port
+ * 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1
+ * # ports
+ * 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2
+ * # port
+ * 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port
+ * 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration)
+ *
+ * if there is a port/phy on which you do not wish to override the default
+ * values, use the value assigned to UNINIT_PARAM (255).
+ */
+unsigned int phy_mask[] = { 1, 2, 4, 8, 1, 2, 4, 8 };
+
+
+/* denotes SAS generation. i.e. 3: SAS Gen 3 6G */
+unsigned int phy_gen[] = { 3, 3, 3, 3, 3, 3, 3, 3 };
+
+/*
+ * if there is a port/phy on which you do not wish to override the default
+ * values, use the value "0000000000000000". SAS address of zero's is
+ * considered invalid and will not be used.
+ */
+unsigned long long sas_addr[] = { 0x5FCFFFFFF0000000ULL,
+ 0x5FCFFFFFF1000000ULL,
+ 0x5FCFFFFFF2000000ULL,
+ 0x5FCFFFFFF3000000ULL,
+ 0x5FCFFFFFF4000000ULL,
+ 0x5FCFFFFFF5000000ULL,
+ 0x5FCFFFFFF6000000ULL,
+ 0x5FCFFFFFF7000000ULL };
+
+int write_blob(void)
+{
+ FILE *fd;
+ int err;
+
+ fd = fopen(blob_name, "w+");
+ if (!fd) {
+ perror("Open file for write failed");
+ return -EIO;
+ }
+
+ /* write id */
+ err = fwrite((void *)id, sizeof(char), strlen(id)+1, fd);
+ if (err == 0) {
+ perror("write id failed");
+ return err;
+ }
+
+ /* write version */
+ err = fwrite((void *)&version, sizeof(version), 1, fd);
+ if (err == 0) {
+ perror("write version failed");
+ return err;
+ }
+
+ /* write sub version */
+ err = fwrite((void *)&sub_version, sizeof(sub_version), 1, fd);
+ if (err == 0) {
+ perror("write subversion failed");
+ return err;
+ }
+
+ /* write phy mask header */
+ err = fputc(0x1, fd);
+ if (err == EOF) {
+ perror("write phy mask header failed");
+ return -EIO;
+ }
+
+ /* write size */
+ err = fputc(8, fd);
+ if (err == EOF) {
+ perror("write phy mask size failed");
+ return -EIO;
+ }
+
+ /* write phy masks */
+ err = fwrite((void *)phy_mask, 1, sizeof(phy_mask), fd);
+ if (err == 0) {
+ perror("write phy_mask failed");
+ return err;
+ }
+
+ /* write phy gen header */
+ err = fputc(0x2, fd);
+ if (err == EOF) {
+ perror("write phy gen header failed");
+ return -EIO;
+ }
+
+ /* write size */
+ err = fputc(8, fd);
+ if (err == EOF) {
+ perror("write phy gen size failed");
+ return -EIO;
+ }
+
+ /* write phy_gen */
+ err = fwrite((void *)phy_gen,
+ 1,
+ sizeof(phy_gen),
+ fd);
+ if (err == 0) {
+ perror("write phy_gen failed");
+ return err;
+ }
+
+ /* write phy gen header */
+ err = fputc(0x3, fd);
+ if (err == EOF) {
+ perror("write sas addr header failed");
+ return -EIO;
+ }
+
+ /* write size */
+ err = fputc(8, fd);
+ if (err == EOF) {
+ perror("write sas addr size failed");
+ return -EIO;
+ }
+
+ /* write sas_addr */
+ err = fwrite((void *)sas_addr,
+ 1,
+ sizeof(sas_addr),
+ fd);
+ if (err == 0) {
+ perror("write sas_addr failed");
+ return err;
+ }
+
+ /* write end header */
+ err = fputc(0xff, fd);
+ if (err == EOF) {
+ perror("write end header failed");
+ return -EIO;
+ }
+
+ fclose(fd);
+
+ return 0;
+}
+
+int main(void)
+{
+ int err;
+
+ err = write_blob();
+ if (err < 0)
+ return err;
+
+ return 0;
+}