• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/rtl8192e/
1/*
2 * Procedure: Init boot code/firmware code/data session
3 *
4 * Description: This routine will intialize firmware. If any error occurs
5 *		during the initialization process, the routine shall terminate
6 *		immediately and return fail.  NIC driver should call
7 *		NdisOpenFile only from MiniportInitialize.
8 *
9 * Arguments:   The pointer of the adapter
10 *
11 * Returns:
12 *		NDIS_STATUS_FAILURE - the following initialization process
13 *				      should be terminated
14 *		NDIS_STATUS_SUCCESS - if firmware initialization process
15 *				      success
16 */
17
18#include "r8192E.h"
19#include "r8192E_hw.h"
20
21#include <linux/firmware.h>
22
23/* It should be double word alignment */
24#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4 * (v / 4) - 8)
25
26enum firmware_init_step {
27	FW_INIT_STEP0_BOOT = 0,
28	FW_INIT_STEP1_MAIN = 1,
29	FW_INIT_STEP2_DATA = 2,
30};
31
32enum opt_rst_type {
33	OPT_SYSTEM_RESET = 0,
34	OPT_FIRMWARE_RESET = 1,
35};
36
37void firmware_init_param(struct net_device *dev)
38{
39	struct r8192_priv *priv = ieee80211_priv(dev);
40	rt_firmware *pfirmware = priv->pFirmware;
41
42	pfirmware->cmdpacket_frag_thresold =
43		GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE);
44}
45
46/*
47 * segment the img and use the ptr and length to remember info on each segment
48 */
49static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
50			     u32 buffer_len)
51{
52	struct r8192_priv *priv = ieee80211_priv(dev);
53	bool rt_status = true;
54	u16 frag_threshold;
55	u16 frag_length, frag_offset = 0;
56	int i;
57
58	rt_firmware *pfirmware = priv->pFirmware;
59	struct sk_buff *skb;
60	unsigned char *seg_ptr;
61	cb_desc *tcb_desc;
62	u8 bLastIniPkt;
63
64	firmware_init_param(dev);
65
66	/* Fragmentation might be required */
67	frag_threshold = pfirmware->cmdpacket_frag_thresold;
68	do {
69		if ((buffer_len - frag_offset) > frag_threshold) {
70			frag_length = frag_threshold ;
71			bLastIniPkt = 0;
72		} else {
73			frag_length = buffer_len - frag_offset;
74			bLastIniPkt = 1;
75		}
76
77		/*
78		 * Allocate skb buffer to contain firmware info and tx
79		 * descriptor info add 4 to avoid packet appending overflow.
80		 */
81		skb  = dev_alloc_skb(frag_length + 4);
82		memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
83		tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
84		tcb_desc->queue_index = TXCMD_QUEUE;
85		tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
86		tcb_desc->bLastIniPkt = bLastIniPkt;
87
88		seg_ptr = skb->data;
89
90		/*
91		 * Transform from little endian to big endian and pending zero
92		 */
93		for (i = 0; i < frag_length; i += 4) {
94			*seg_ptr++ = ((i+0) < frag_length) ? \
95					code_virtual_address[i+3] : 0;
96
97			*seg_ptr++ = ((i+1) < frag_length) ? \
98					code_virtual_address[i+2] : 0;
99
100			*seg_ptr++ = ((i+2) < frag_length) ? \
101					code_virtual_address[i+1] : 0;
102
103			*seg_ptr++ = ((i+3) < frag_length) ? \
104					code_virtual_address[i+0] : 0;
105		}
106		tcb_desc->txbuf_size = (u16)i;
107		skb_put(skb, i);
108		priv->ieee80211->softmac_hard_start_xmit(skb, dev);
109
110		code_virtual_address += frag_length;
111		frag_offset += frag_length;
112
113	} while (frag_offset < buffer_len);
114
115	return rt_status;
116}
117
118/*
119 * Procedure:    Check whether main code is download OK. If OK, turn on CPU
120 *
121 * Description:   CPU register locates in different page against general
122 *		  register.  Switch to CPU register in the begin and switch
123 *		  back before return
124 *
125 * Arguments:   The pointer of the adapter
126 *
127 * Returns:
128 *	NDIS_STATUS_FAILURE - the following initialization process should be
129 *			      terminated
130 *	NDIS_STATUS_SUCCESS - if firmware initialization process success
131 */
132static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
133{
134	unsigned long timeout;
135	bool rt_status = true;
136	u32 CPU_status = 0;
137
138	/* Check whether put code OK */
139	timeout = jiffies + msecs_to_jiffies(20);
140	while (time_before(jiffies, timeout)) {
141		CPU_status = read_nic_dword(dev, CPU_GEN);
142
143		if (CPU_status & CPU_GEN_PUT_CODE_OK)
144			break;
145		msleep(2);
146	}
147
148	if (!(CPU_status & CPU_GEN_PUT_CODE_OK)) {
149		RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n");
150		goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
151	} else {
152		RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
153	}
154
155	/* Turn On CPU */
156	CPU_status = read_nic_dword(dev, CPU_GEN);
157	write_nic_byte(dev, CPU_GEN,
158		       (u8)((CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff));
159	mdelay(1);
160
161	/* Check whether CPU boot OK */
162	timeout = jiffies + msecs_to_jiffies(20);
163	while (time_before(jiffies, timeout)) {
164		CPU_status = read_nic_dword(dev, CPU_GEN);
165
166		if (CPU_status & CPU_GEN_BOOT_RDY)
167			break;
168		msleep(2);
169	}
170
171	if (!(CPU_status & CPU_GEN_BOOT_RDY))
172		goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
173	else
174		RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
175
176	return rt_status;
177
178CPUCheckMainCodeOKAndTurnOnCPU_Fail:
179	RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
180	rt_status = FALSE;
181	return rt_status;
182}
183
184static bool CPUcheck_firmware_ready(struct net_device *dev)
185{
186	unsigned long timeout;
187	bool rt_status = true;
188	u32 CPU_status = 0;
189
190	/* Check Firmware Ready */
191	timeout = jiffies + msecs_to_jiffies(20);
192	while (time_before(jiffies, timeout)) {
193		CPU_status = read_nic_dword(dev, CPU_GEN);
194
195		if (CPU_status & CPU_GEN_FIRM_RDY)
196			break;
197		msleep(2);
198	}
199
200	if (!(CPU_status & CPU_GEN_FIRM_RDY))
201		goto CPUCheckFirmwareReady_Fail;
202	else
203		RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
204
205	return rt_status;
206
207CPUCheckFirmwareReady_Fail:
208	RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
209	rt_status = false;
210	return rt_status;
211
212}
213
214bool init_firmware(struct net_device *dev)
215{
216	struct r8192_priv *priv = ieee80211_priv(dev);
217	bool rt_status = true;
218	u32 file_length = 0;
219	u8 *mapped_file = NULL;
220	u32 init_step = 0;
221	enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
222	enum firmware_init_step	starting_state = FW_INIT_STEP0_BOOT;
223
224	rt_firmware *pfirmware = priv->pFirmware;
225	const struct firmware *fw_entry;
226	const char *fw_name[3] = { "RTL8192E/boot.img",
227				   "RTL8192E/main.img",
228				   "RTL8192E/data.img"};
229	int rc;
230
231	RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
232
233	if (pfirmware->firmware_status == FW_STATUS_0_INIT) {
234		/* it is called by reset */
235		rst_opt = OPT_SYSTEM_RESET;
236		starting_state = FW_INIT_STEP0_BOOT;
237		/* TODO: system reset */
238
239	} else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
240		/* it is called by Initialize */
241		rst_opt = OPT_FIRMWARE_RESET;
242		starting_state = FW_INIT_STEP2_DATA;
243	} else {
244		RT_TRACE(COMP_FIRMWARE,
245			"PlatformInitFirmware: undefined firmware state\n");
246	}
247
248	/*
249	 * Download boot, main, and data image for System reset.
250	 * Download data image for firmware reseta
251	 */
252	for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; \
253			init_step++) {
254		/*
255		 * Open Image file, and map file to contineous memory if open file success.
256		 * or read image file from array. Default load from IMG file
257		 */
258		if (rst_opt == OPT_SYSTEM_RESET) {
259			if (pfirmware->firmware_buf_size[init_step] == 0) {
260				rc = request_firmware(&fw_entry,
261					fw_name[init_step], &priv->pdev->dev);
262
263				if (rc < 0) {
264					RT_TRACE(COMP_FIRMWARE, "request firmware fail!\n");
265					goto download_firmware_fail;
266				}
267
268				if (fw_entry->size > sizeof(pfirmware->firmware_buf[init_step])) {
269					RT_TRACE(COMP_FIRMWARE, \
270						"img file size exceed the container buffer fail!\n");
271					goto download_firmware_fail;
272				}
273
274				if (init_step != FW_INIT_STEP1_MAIN) {
275					memcpy(pfirmware->firmware_buf[init_step],
276							fw_entry->data, fw_entry->size);
277					pfirmware->firmware_buf_size[init_step] = fw_entry->size;
278
279				} else {
280					memset(pfirmware->firmware_buf[init_step], 0, 128);
281					memcpy(&pfirmware->firmware_buf[init_step][128], fw_entry->data,
282									fw_entry->size);
283					pfirmware->firmware_buf_size[init_step] = fw_entry->size+128;
284				}
285
286				if (rst_opt == OPT_SYSTEM_RESET)
287					release_firmware(fw_entry);
288			}
289			mapped_file = pfirmware->firmware_buf[init_step];
290			file_length = pfirmware->firmware_buf_size[init_step];
291
292		} else if (rst_opt == OPT_FIRMWARE_RESET) {
293			/* we only need to download data.img here */
294			mapped_file = pfirmware->firmware_buf[init_step];
295			file_length = pfirmware->firmware_buf_size[init_step];
296		}
297
298		/* Download image file */
299		/* The firmware download process is just as following,
300		 * 1. that is each packet will be segmented and inserted to the
301		 *    wait queue.
302		 * 2. each packet segment will be put in the skb_buff packet.
303		 * 3. each skb_buff packet data content will already include
304		 *    the firmware info and Tx descriptor info
305		 */
306		rt_status = fw_download_code(dev, mapped_file, file_length);
307		if (rt_status != TRUE)
308			goto download_firmware_fail;
309
310		switch (init_step) {
311		case FW_INIT_STEP0_BOOT:
312			/* Download boot
313			 * initialize command descriptor.
314			 * will set polling bit when firmware code is also
315			 * configured
316			 */
317			pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
318			/* mdelay(1000); */
319			/*
320			 * To initialize IMEM, CPU move code  from 0x80000080,
321			 * hence, we send 0x80 byte packet
322			 */
323			break;
324
325		case FW_INIT_STEP1_MAIN:
326			/* Download firmware code.
327			 * Wait until Boot Ready and Turn on CPU */
328			pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
329
330			/* Check Put Code OK and Turn On CPU */
331			rt_status = CPUcheck_maincodeok_turnonCPU(dev);
332			if (rt_status != TRUE) {
333				RT_TRACE(COMP_FIRMWARE,
334					"CPUcheck_maincodeok_turnonCPU fail!\n");
335				goto download_firmware_fail;
336			}
337
338			pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
339			break;
340
341		case FW_INIT_STEP2_DATA:
342			/* download initial data code */
343			pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
344			mdelay(1);
345
346			rt_status = CPUcheck_firmware_ready(dev);
347			if (rt_status != TRUE) {
348				RT_TRACE(COMP_FIRMWARE,
349					"CPUcheck_firmware_ready fail(%d)!\n",
350					rt_status);
351				goto download_firmware_fail;
352			}
353
354			/* wait until data code is initialized ready.*/
355			pfirmware->firmware_status = FW_STATUS_5_READY;
356			break;
357		}
358	}
359
360	RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
361	return rt_status;
362
363download_firmware_fail:
364	RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
365	rt_status = false;
366	return rt_status;
367}
368
369MODULE_FIRMWARE("RTL8192E/boot.img");
370MODULE_FIRMWARE("RTL8192E/main.img");
371MODULE_FIRMWARE("RTL8192E/data.img");
372