aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/isci/firmware/create_fw.c
blob: 442caac9675d643ad5012a184763da138dcf6c35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
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;
}