xref: /dragonfly/sys/dev/netif/ig_hal/e1000_manage.c (revision ed183f8c)
1 /******************************************************************************
2 
3   Copyright (c) 2001-2016, Intel Corporation
4   All rights reserved.
5 
6   Redistribution and use in source and binary forms, with or without
7   modification, are permitted provided that the following conditions are met:
8 
9    1. Redistributions of source code must retain the above copyright notice,
10       this list of conditions and the following disclaimer.
11 
12    2. Redistributions in binary form must reproduce the above copyright
13       notice, this list of conditions and the following disclaimer in the
14       documentation and/or other materials provided with the distribution.
15 
16    3. Neither the name of the Intel Corporation nor the names of its
17       contributors may be used to endorse or promote products derived from
18       this software without specific prior written permission.
19 
20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   POSSIBILITY OF SUCH DAMAGE.
31 
32 ******************************************************************************/
33 /*$FreeBSD$*/
34 
35 #include "e1000_api.h"
36 /**
37  *  e1000_calculate_checksum - Calculate checksum for buffer
38  *  @buffer: pointer to EEPROM
39  *  @length: size of EEPROM to calculate a checksum for
40  *
41  *  Calculates the checksum for some buffer on a specified length.  The
42  *  checksum calculated is returned.
43  **/
44 u8 e1000_calculate_checksum(u8 *buffer, u32 length)
45 {
46 	u32 i;
47 	u8 sum = 0;
48 
49 	DEBUGFUNC("e1000_calculate_checksum");
50 
51 	if (!buffer)
52 		return 0;
53 
54 	for (i = 0; i < length; i++)
55 		sum += buffer[i];
56 
57 	return (u8) (0 - sum);
58 }
59 
60 /**
61  *  e1000_mng_enable_host_if_generic - Checks host interface is enabled
62  *  @hw: pointer to the HW structure
63  *
64  *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
65  *
66  *  This function checks whether the HOST IF is enabled for command operation
67  *  and also checks whether the previous command is completed.  It busy waits
68  *  in case of previous command is not completed.
69  **/
70 s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
71 {
72 	u32 hicr;
73 	u8 i;
74 
75 	DEBUGFUNC("e1000_mng_enable_host_if_generic");
76 
77 	if (!hw->mac.arc_subsystem_valid) {
78 		DEBUGOUT("ARC subsystem not valid.\n");
79 		return -E1000_ERR_HOST_INTERFACE_COMMAND;
80 	}
81 
82 	/* Check that the host interface is enabled. */
83 	hicr = E1000_READ_REG(hw, E1000_HICR);
84 	if (!(hicr & E1000_HICR_EN)) {
85 		DEBUGOUT("E1000_HOST_EN bit disabled.\n");
86 		return -E1000_ERR_HOST_INTERFACE_COMMAND;
87 	}
88 	/* check the previous command is completed */
89 	for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
90 		hicr = E1000_READ_REG(hw, E1000_HICR);
91 		if (!(hicr & E1000_HICR_C))
92 			break;
93 		msec_delay_irq(1);
94 	}
95 
96 	if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
97 		DEBUGOUT("Previous command timeout failed .\n");
98 		return -E1000_ERR_HOST_INTERFACE_COMMAND;
99 	}
100 
101 	return E1000_SUCCESS;
102 }
103 
104 /**
105  *  e1000_check_mng_mode_generic - Generic check management mode
106  *  @hw: pointer to the HW structure
107  *
108  *  Reads the firmware semaphore register and returns TRUE (>0) if
109  *  manageability is enabled, else FALSE (0).
110  **/
111 bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
112 {
113 	u32 fwsm = E1000_READ_REG(hw, E1000_FWSM);
114 
115 	DEBUGFUNC("e1000_check_mng_mode_generic");
116 
117 
118 	return (fwsm & E1000_FWSM_MODE_MASK) ==
119 		(E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
120 }
121 
122 /**
123  *  e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx
124  *  @hw: pointer to the HW structure
125  *
126  *  Enables packet filtering on transmit packets if manageability is enabled
127  *  and host interface is enabled.
128  **/
129 bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
130 {
131 	struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
132 	u32 *buffer = (u32 *)&hw->mng_cookie;
133 	u32 offset;
134 	s32 ret_val, hdr_csum, csum;
135 	u8 i, len;
136 
137 	DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
138 
139 	hw->mac.tx_pkt_filtering = TRUE;
140 
141 	/* No manageability, no filtering */
142 	if (!hw->mac.ops.check_mng_mode(hw)) {
143 		hw->mac.tx_pkt_filtering = FALSE;
144 		return hw->mac.tx_pkt_filtering;
145 	}
146 
147 	/* If we can't read from the host interface for whatever
148 	 * reason, disable filtering.
149 	 */
150 	ret_val = e1000_mng_enable_host_if_generic(hw);
151 	if (ret_val != E1000_SUCCESS) {
152 		hw->mac.tx_pkt_filtering = FALSE;
153 		return hw->mac.tx_pkt_filtering;
154 	}
155 
156 	/* Read in the header.  Length and offset are in dwords. */
157 	len    = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
158 	offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
159 	for (i = 0; i < len; i++)
160 		*(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
161 							   offset + i);
162 	hdr_csum = hdr->checksum;
163 	hdr->checksum = 0;
164 	csum = e1000_calculate_checksum((u8 *)hdr,
165 					E1000_MNG_DHCP_COOKIE_LENGTH);
166 	/* If either the checksums or signature don't match, then
167 	 * the cookie area isn't considered valid, in which case we
168 	 * take the safe route of assuming Tx filtering is enabled.
169 	 */
170 	if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
171 		hw->mac.tx_pkt_filtering = TRUE;
172 		return hw->mac.tx_pkt_filtering;
173 	}
174 
175 	/* Cookie area is valid, make the final check for filtering. */
176 	if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
177 		hw->mac.tx_pkt_filtering = FALSE;
178 
179 	return hw->mac.tx_pkt_filtering;
180 }
181 
182 /**
183  *  e1000_mng_write_cmd_header_generic - Writes manageability command header
184  *  @hw: pointer to the HW structure
185  *  @hdr: pointer to the host interface command header
186  *
187  *  Writes the command header after does the checksum calculation.
188  **/
189 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
190 				      struct e1000_host_mng_command_header *hdr)
191 {
192 	u16 i, length = sizeof(struct e1000_host_mng_command_header);
193 
194 	DEBUGFUNC("e1000_mng_write_cmd_header_generic");
195 
196 	/* Write the whole command header structure with new checksum. */
197 
198 	hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
199 
200 	length >>= 2;
201 	/* Write the relevant command block into the ram area. */
202 	for (i = 0; i < length; i++) {
203 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
204 					    *((u32 *) hdr + i));
205 		E1000_WRITE_FLUSH(hw);
206 	}
207 
208 	return E1000_SUCCESS;
209 }
210 
211 /**
212  *  e1000_mng_host_if_write_generic - Write to the manageability host interface
213  *  @hw: pointer to the HW structure
214  *  @buffer: pointer to the host interface buffer
215  *  @length: size of the buffer
216  *  @offset: location in the buffer to write to
217  *  @sum: sum of the data (not checksum)
218  *
219  *  This function writes the buffer content at the offset given on the host if.
220  *  It also does alignment considerations to do the writes in most efficient
221  *  way.  Also fills up the sum of the buffer in *buffer parameter.
222  **/
223 s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
224 				    u16 length, u16 offset, u8 *sum)
225 {
226 	u8 *tmp;
227 	u8 *bufptr = buffer;
228 	u32 data = 0;
229 	u16 remaining, i, j, prev_bytes;
230 
231 	DEBUGFUNC("e1000_mng_host_if_write_generic");
232 
233 	/* sum = only sum of the data and it is not checksum */
234 
235 	if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
236 		return -E1000_ERR_PARAM;
237 
238 	tmp = (u8 *)&data;
239 	prev_bytes = offset & 0x3;
240 	offset >>= 2;
241 
242 	if (prev_bytes) {
243 		data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
244 		for (j = prev_bytes; j < sizeof(u32); j++) {
245 			*(tmp + j) = *bufptr++;
246 			*sum += *(tmp + j);
247 		}
248 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
249 		length -= j - prev_bytes;
250 		offset++;
251 	}
252 
253 	remaining = length & 0x3;
254 	length -= remaining;
255 
256 	/* Calculate length in DWORDs */
257 	length >>= 2;
258 
259 	/* The device driver writes the relevant command block into the
260 	 * ram area.
261 	 */
262 	for (i = 0; i < length; i++) {
263 		for (j = 0; j < sizeof(u32); j++) {
264 			*(tmp + j) = *bufptr++;
265 			*sum += *(tmp + j);
266 		}
267 
268 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
269 					    data);
270 	}
271 	if (remaining) {
272 		for (j = 0; j < sizeof(u32); j++) {
273 			if (j < remaining)
274 				*(tmp + j) = *bufptr++;
275 			else
276 				*(tmp + j) = 0;
277 
278 			*sum += *(tmp + j);
279 		}
280 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
281 					    data);
282 	}
283 
284 	return E1000_SUCCESS;
285 }
286 
287 /**
288  *  e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
289  *  @hw: pointer to the HW structure
290  *  @buffer: pointer to the host interface
291  *  @length: size of the buffer
292  *
293  *  Writes the DHCP information to the host interface.
294  **/
295 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
296 				      u16 length)
297 {
298 	struct e1000_host_mng_command_header hdr;
299 	s32 ret_val;
300 	u32 hicr;
301 
302 	DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
303 
304 	hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
305 	hdr.command_length = length;
306 	hdr.reserved1 = 0;
307 	hdr.reserved2 = 0;
308 	hdr.checksum = 0;
309 
310 	/* Enable the host interface */
311 	ret_val = e1000_mng_enable_host_if_generic(hw);
312 	if (ret_val)
313 		return ret_val;
314 
315 	/* Populate the host interface with the contents of "buffer". */
316 	ret_val = e1000_mng_host_if_write_generic(hw, buffer, length,
317 						  sizeof(hdr), &(hdr.checksum));
318 	if (ret_val)
319 		return ret_val;
320 
321 	/* Write the manageability command header */
322 	ret_val = e1000_mng_write_cmd_header_generic(hw, &hdr);
323 	if (ret_val)
324 		return ret_val;
325 
326 	/* Tell the ARC a new command is pending. */
327 	hicr = E1000_READ_REG(hw, E1000_HICR);
328 	E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
329 
330 	return E1000_SUCCESS;
331 }
332 
333 /**
334  *  e1000_enable_mng_pass_thru - Check if management passthrough is needed
335  *  @hw: pointer to the HW structure
336  *
337  *  Verifies the hardware needs to leave interface enabled so that frames can
338  *  be directed to and from the management interface.
339  **/
340 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
341 {
342 	u32 manc;
343 	u32 fwsm, factps;
344 
345 	DEBUGFUNC("e1000_enable_mng_pass_thru");
346 
347 	if (!hw->mac.asf_firmware_present)
348 		return FALSE;
349 
350 	manc = E1000_READ_REG(hw, E1000_MANC);
351 
352 	if (!(manc & E1000_MANC_RCV_TCO_EN))
353 		return FALSE;
354 
355 	if (hw->mac.has_fwsm) {
356 		fwsm = E1000_READ_REG(hw, E1000_FWSM);
357 		factps = E1000_READ_REG(hw, E1000_FACTPS);
358 
359 		if (!(factps & E1000_FACTPS_MNGCG) &&
360 		    ((fwsm & E1000_FWSM_MODE_MASK) ==
361 		     (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)))
362 			return TRUE;
363 	} else if ((hw->mac.type == e1000_82574) ||
364 		   (hw->mac.type == e1000_82583)) {
365 		u16 data;
366 		s32 ret_val;
367 
368 		factps = E1000_READ_REG(hw, E1000_FACTPS);
369 		ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
370 		if (ret_val)
371 			return FALSE;
372 
373 		if (!(factps & E1000_FACTPS_MNGCG) &&
374 		    ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
375 		     (e1000_mng_mode_pt << 13)))
376 			return TRUE;
377 	} else if ((manc & E1000_MANC_SMBUS_EN) &&
378 		   !(manc & E1000_MANC_ASF_EN)) {
379 		return TRUE;
380 	}
381 
382 	return FALSE;
383 }
384 
385 /**
386  *  e1000_host_interface_command - Writes buffer to host interface
387  *  @hw: pointer to the HW structure
388  *  @buffer: contains a command to write
389  *  @length: the byte length of the buffer, must be multiple of 4 bytes
390  *
391  *  Writes a buffer to the Host Interface.  Upon success, returns E1000_SUCCESS
392  *  else returns E1000_ERR_HOST_INTERFACE_COMMAND.
393  **/
394 s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
395 {
396 	u32 hicr, i;
397 
398 	DEBUGFUNC("e1000_host_interface_command");
399 
400 	if (!(hw->mac.arc_subsystem_valid)) {
401 		DEBUGOUT("Hardware doesn't support host interface command.\n");
402 		return E1000_SUCCESS;
403 	}
404 
405 	if (!hw->mac.asf_firmware_present) {
406 		DEBUGOUT("Firmware is not present.\n");
407 		return E1000_SUCCESS;
408 	}
409 
410 	if (length == 0 || length & 0x3 ||
411 	    length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) {
412 		DEBUGOUT("Buffer length failure.\n");
413 		return -E1000_ERR_HOST_INTERFACE_COMMAND;
414 	}
415 
416 	/* Check that the host interface is enabled. */
417 	hicr = E1000_READ_REG(hw, E1000_HICR);
418 	if (!(hicr & E1000_HICR_EN)) {
419 		DEBUGOUT("E1000_HOST_EN bit disabled.\n");
420 		return -E1000_ERR_HOST_INTERFACE_COMMAND;
421 	}
422 
423 	/* Calculate length in DWORDs */
424 	length >>= 2;
425 
426 	/* The device driver writes the relevant command block
427 	 * into the ram area.
428 	 */
429 	for (i = 0; i < length; i++)
430 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
431 					    *((u32 *)buffer + i));
432 
433 	/* Setting this bit tells the ARC that a new command is pending. */
434 	E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
435 
436 	for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
437 		hicr = E1000_READ_REG(hw, E1000_HICR);
438 		if (!(hicr & E1000_HICR_C))
439 			break;
440 		msec_delay(1);
441 	}
442 
443 	/* Check command successful completion. */
444 	if (i == E1000_HI_COMMAND_TIMEOUT ||
445 	    (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) {
446 		DEBUGOUT("Command has failed with no status valid.\n");
447 		return -E1000_ERR_HOST_INTERFACE_COMMAND;
448 	}
449 
450 	for (i = 0; i < length; i++)
451 		*((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
452 								  E1000_HOST_IF,
453 								  i);
454 
455 	return E1000_SUCCESS;
456 }
457 /**
458  *  e1000_load_firmware - Writes proxy FW code buffer to host interface
459  *                        and execute.
460  *  @hw: pointer to the HW structure
461  *  @buffer: contains a firmware to write
462  *  @length: the byte length of the buffer, must be multiple of 4 bytes
463  *
464  *  Upon success returns E1000_SUCCESS, returns E1000_ERR_CONFIG if not enabled
465  *  in HW else returns E1000_ERR_HOST_INTERFACE_COMMAND.
466  **/
467 s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length)
468 {
469 	u32 hicr, hibba, fwsm, icr, i;
470 
471 	DEBUGFUNC("e1000_load_firmware");
472 
473 	if (hw->mac.type < e1000_i210) {
474 		DEBUGOUT("Hardware doesn't support loading FW by the driver\n");
475 		return -E1000_ERR_CONFIG;
476 	}
477 
478 	/* Check that the host interface is enabled. */
479 	hicr = E1000_READ_REG(hw, E1000_HICR);
480 	if (!(hicr & E1000_HICR_EN)) {
481 		DEBUGOUT("E1000_HOST_EN bit disabled.\n");
482 		return -E1000_ERR_CONFIG;
483 	}
484 	if (!(hicr & E1000_HICR_MEMORY_BASE_EN)) {
485 		DEBUGOUT("E1000_HICR_MEMORY_BASE_EN bit disabled.\n");
486 		return -E1000_ERR_CONFIG;
487 	}
488 
489 	if (length == 0 || length & 0x3 || length > E1000_HI_FW_MAX_LENGTH) {
490 		DEBUGOUT("Buffer length failure.\n");
491 		return -E1000_ERR_INVALID_ARGUMENT;
492 	}
493 
494 	/* Clear notification from ROM-FW by reading ICR register */
495 	icr = E1000_READ_REG(hw, E1000_ICR_V2);
496 
497 	/* Reset ROM-FW */
498 	hicr = E1000_READ_REG(hw, E1000_HICR);
499 	hicr |= E1000_HICR_FW_RESET_ENABLE;
500 	E1000_WRITE_REG(hw, E1000_HICR, hicr);
501 	hicr |= E1000_HICR_FW_RESET;
502 	E1000_WRITE_REG(hw, E1000_HICR, hicr);
503 	E1000_WRITE_FLUSH(hw);
504 
505 	/* Wait till MAC notifies about its readiness after ROM-FW reset */
506 	for (i = 0; i < (E1000_HI_COMMAND_TIMEOUT * 2); i++) {
507 		icr = E1000_READ_REG(hw, E1000_ICR_V2);
508 		if (icr & E1000_ICR_MNG)
509 			break;
510 		msec_delay(1);
511 	}
512 
513 	/* Check for timeout */
514 	if (i == E1000_HI_COMMAND_TIMEOUT) {
515 		DEBUGOUT("FW reset failed.\n");
516 		return -E1000_ERR_HOST_INTERFACE_COMMAND;
517 	}
518 
519 	/* Wait till MAC is ready to accept new FW code */
520 	for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
521 		fwsm = E1000_READ_REG(hw, E1000_FWSM);
522 		if ((fwsm & E1000_FWSM_FW_VALID) &&
523 		    ((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT ==
524 		    E1000_FWSM_HI_EN_ONLY_MODE))
525 			break;
526 		msec_delay(1);
527 	}
528 
529 	/* Check for timeout */
530 	if (i == E1000_HI_COMMAND_TIMEOUT) {
531 		DEBUGOUT("FW reset failed.\n");
532 		return -E1000_ERR_HOST_INTERFACE_COMMAND;
533 	}
534 
535 	/* Calculate length in DWORDs */
536 	length >>= 2;
537 
538 	/* The device driver writes the relevant FW code block
539 	 * into the ram area in DWORDs via 1kB ram addressing window.
540 	 */
541 	for (i = 0; i < length; i++) {
542 		if (!(i % E1000_HI_FW_BLOCK_DWORD_LENGTH)) {
543 			/* Point to correct 1kB ram window */
544 			hibba = E1000_HI_FW_BASE_ADDRESS +
545 				((E1000_HI_FW_BLOCK_DWORD_LENGTH << 2) *
546 				(i / E1000_HI_FW_BLOCK_DWORD_LENGTH));
547 
548 			E1000_WRITE_REG(hw, E1000_HIBBA, hibba);
549 		}
550 
551 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
552 					    i % E1000_HI_FW_BLOCK_DWORD_LENGTH,
553 					    *((u32 *)buffer + i));
554 	}
555 
556 	/* Setting this bit tells the ARC that a new FW is ready to execute. */
557 	hicr = E1000_READ_REG(hw, E1000_HICR);
558 	E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
559 
560 	for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
561 		hicr = E1000_READ_REG(hw, E1000_HICR);
562 		if (!(hicr & E1000_HICR_C))
563 			break;
564 		msec_delay(1);
565 	}
566 
567 	/* Check for successful FW start. */
568 	if (i == E1000_HI_COMMAND_TIMEOUT) {
569 		DEBUGOUT("New FW did not start within timeout period.\n");
570 		return -E1000_ERR_HOST_INTERFACE_COMMAND;
571 	}
572 
573 	return E1000_SUCCESS;
574 }
575 
576 
577