diff options
Diffstat (limited to 'drivers/scsi/isci/firmware')
-rw-r--r-- | drivers/scsi/isci/firmware/Makefile | 19 | ||||
-rw-r--r-- | drivers/scsi/isci/firmware/README | 36 | ||||
-rw-r--r-- | drivers/scsi/isci/firmware/create_fw.c | 177 |
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; +} |