linux/drivers/scsi/isci/firmware/create_fw.c
Dan Williams 6f231dda68 isci: Intel(R) C600 Series Chipset Storage Control Unit Driver
Support for the up to 2x4-port 6Gb/s SAS controllers embedded in the
chipset.

This is a snapshot of the first publicly available version of the driver,
commit 4c1db2d0 in the 'historical' branch.

   git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git historical

Signed-off-by: Maciej Trela <maciej.trela@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Edmund Nadolski <edmund.nadolski@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
2011-07-02 22:56:22 -07:00

178 lines
3.6 KiB
C

#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;
}