xref: /titanic_41/usr/src/uts/common/io/sdcard/impl/sda_init.c (revision f2b90c3c415ff04d4adb3a54242822b41d74bfd9)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * SD card initialization support.
28  */
29 
30 #include <sys/types.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/sdcard/sda.h>
34 #include <sys/sdcard/sda_impl.h>
35 
36 
37 /*
38  * Local Prototypes.
39  */
40 
41 static sda_err_t sda_init_mmc(sda_slot_t *);
42 static sda_err_t sda_init_sdio(sda_slot_t *);
43 static sda_err_t sda_init_sdmem(sda_slot_t *);
44 static sda_err_t sda_init_cmd(sda_slot_t *, sda_index_t, uint32_t,
45     sda_rtype_t, uint32_t *);
46 static sda_err_t sda_init_acmd(sda_slot_t *, sda_index_t, uint32_t,
47     sda_rtype_t, uint32_t *);
48 static sda_err_t sda_init_blocklen(sda_slot_t *);
49 static sda_err_t sda_init_width(sda_slot_t *);
50 static sda_err_t sda_init_rca(sda_slot_t *);
51 static sda_err_t sda_init_ifcond(sda_slot_t *);
52 static sda_err_t sda_init_highspeed(sda_slot_t *);
53 static sda_err_t sda_init_switch(sda_slot_t *, uint8_t, uint8_t, uint8_t,
54     uint8_t *);
55 static void sda_init_clock(sda_slot_t *, uint32_t);
56 
57 /*
58  * Implementation.
59  */
60 sda_err_t
sda_init_cmd(sda_slot_t * slot,sda_index_t cmd,uint32_t arg,sda_rtype_t rtype,uint32_t * resp)61 sda_init_cmd(sda_slot_t *slot, sda_index_t cmd, uint32_t arg,
62     sda_rtype_t rtype, uint32_t *resp)
63 {
64 	sda_cmd_t	*cmdp;
65 	sda_err_t	errno;
66 
67 	cmdp = sda_cmd_alloc(slot, cmd, arg, rtype, NULL, KM_SLEEP);
68 
69 	cmdp->sc_flags |= SDA_CMDF_INIT;
70 
71 	errno = sda_cmd_exec(slot, cmdp, resp);
72 
73 	sda_cmd_free(cmdp);
74 
75 	return (errno);
76 }
77 
78 sda_err_t
sda_init_acmd(sda_slot_t * slot,sda_index_t cmd,uint32_t arg,sda_rtype_t rtype,uint32_t * resp)79 sda_init_acmd(sda_slot_t *slot, sda_index_t cmd, uint32_t arg,
80     sda_rtype_t rtype, uint32_t *resp)
81 {
82 	sda_cmd_t	*cmdp;
83 	sda_err_t	errno;
84 
85 	cmdp = sda_cmd_alloc_acmd(slot, cmd, arg, rtype, NULL, KM_SLEEP);
86 
87 	cmdp->sc_flags |= SDA_CMDF_INIT;
88 
89 	errno = sda_cmd_exec(slot, cmdp, resp);
90 
91 	sda_cmd_free(cmdp);
92 
93 	return (errno);
94 }
95 
96 sda_err_t
sda_init_sdio(sda_slot_t * slot)97 sda_init_sdio(sda_slot_t *slot)
98 {
99 	slot->s_num_io = 0;
100 
101 	/*
102 	 * TODO: SDIO: We need to initialize the SDIO OCR register using
103 	 * the special CMD_IO_SEND_OCR (CMD5) command.
104 	 */
105 	return (SDA_EOK);
106 }
107 
108 sda_err_t
sda_init_sdmem(sda_slot_t * slot)109 sda_init_sdmem(sda_slot_t *slot)
110 {
111 	uint32_t	ocr;
112 	int		count;
113 
114 	slot->s_flags &= ~SLOTF_SDMEM;
115 
116 	/*
117 	 * Try sending the ACMD41 to query the OCR (Op Cond Register).
118 	 */
119 	if (sda_init_acmd(slot, ACMD_SD_SEND_OCR, 0, R3, &ocr) != SDA_EOK) {
120 		/*
121 		 * Card failed to respond to query, not an SD card?
122 		 * We send GO_IDLE to clear any error status on the
123 		 * card.
124 		 */
125 		(void) sda_init_cmd(slot, CMD_GO_IDLE, 0, R0, NULL);
126 		return (SDA_EOK);
127 	}
128 
129 	/*
130 	 * Now we have to send our OCR value, along with the HCS (High
131 	 * Capacity Support) bit.  The HCS bit is required, to
132 	 * activate high capacity cards.  We only set the HCS bit if
133 	 * the card responded to CMD8 (SEND_IFCOND), indicating that
134 	 * it supports the new protocol.
135 	 *
136 	 * Note that the HCS bit occupies the same location as the CCS bit
137 	 * in the response.
138 	 */
139 	if ((ocr & slot->s_cur_ocr) == 0) {
140 		sda_slot_err(slot, "SD card not compatible with host");
141 		return (SDA_ENOTSUP);
142 	}
143 	/* set the HCS bit if its a ver 2.00 card */
144 	if (slot->s_flags & SLOTF_IFCOND) {
145 		ocr |= OCR_CCS;
146 	}
147 
148 	/* make sure card is powered up */
149 	for (count = 1000000; count != 0; count -= 10000) {
150 		uint32_t	r3;
151 
152 		if (sda_init_acmd(slot, ACMD_SD_SEND_OCR, ocr, R3, &r3) != 0) {
153 			sda_slot_err(slot, "SD card failed to power up");
154 			return (SDA_ENOTSUP);
155 		}
156 
157 		/* Now check the busy bit */
158 		if (r3 & OCR_POWER_UP) {
159 			slot->s_flags |= SLOTF_SDMEM;
160 			if ((slot->s_flags & SLOTF_IFCOND) &&
161 			    (r3 & OCR_CCS)) {
162 				slot->s_flags |= SLOTF_SDHC;
163 			} else {
164 				slot->s_flags &= ~SLOTF_SDHC;
165 			}
166 			return (0);
167 		}
168 
169 		drv_usecwait(10000);
170 	}
171 
172 	sda_slot_err(slot, "SD card timed out during power up");
173 	return (SDA_ETIME);
174 }
175 
176 sda_err_t
sda_init_mmc(sda_slot_t * slot)177 sda_init_mmc(sda_slot_t *slot)
178 {
179 	uint32_t	ocr;
180 	int		count;
181 
182 	slot->s_flags &= ~SLOTF_MMC;
183 
184 	/*
185 	 * If the card has already been identified as an SD card, then
186 	 * cannot also be an MMC card, so don't probe it as such.
187 	 */
188 	if (slot->s_flags & SLOTF_SD) {
189 		return (SDA_EOK);
190 	}
191 
192 	/*
193 	 * Try sending the CMD1 to query the OCR.
194 	 */
195 	if (sda_init_cmd(slot, CMD_SEND_OCR, 0, R3, &ocr) != 0) {
196 		/*
197 		 * Card failed to respond to query, not an MMC card?
198 		 * We send GO_IDLE to clear any error status on the
199 		 * card.
200 		 */
201 		(void) sda_init_cmd(slot, CMD_GO_IDLE, 0, R0, NULL);
202 		return (SDA_EOK);
203 	}
204 
205 	if ((ocr & slot->s_cur_ocr) == 0) {
206 		sda_slot_err(slot, "MMC card not compatible with host");
207 		return (SDA_ENOTSUP);
208 	}
209 
210 	/* make sure card is powered up */
211 	for (count = 1000000; count != 0; count -= 10000) {
212 		uint32_t	r3;
213 
214 		if (sda_init_cmd(slot, CMD_SEND_OCR, ocr, R3, &r3) != 0) {
215 			sda_slot_err(slot, "MMC card failed to power up");
216 			return (SDA_ENOTSUP);
217 		}
218 
219 		/* Now check the busy bit */
220 		if (r3 & OCR_POWER_UP) {
221 			slot->s_flags |= SLOTF_MMC;
222 			return (SDA_EOK);
223 		}
224 
225 		drv_usecwait(10000);
226 	}
227 
228 	sda_slot_err(slot, "MMC card timed out during power up");
229 	return (SDA_ETIME);
230 }
231 
232 sda_err_t
sda_init_card(sda_slot_t * slot)233 sda_init_card(sda_slot_t *slot)
234 {
235 	int		rv;
236 	uint32_t	resp;
237 	uint32_t	val;
238 
239 	/*
240 	 * Power off slot/card initially.
241 	 */
242 	sda_slot_power_off(slot);
243 
244 	/*
245 	 * Apply initial power to the slot.
246 	 */
247 	if ((rv = sda_slot_power_on(slot)) != 0) {
248 		return (rv);
249 	}
250 
251 	/*
252 	 * First enable the clock, but only at 400 kHz.  All cards are
253 	 * supposed to be able to operate between this speed and 100
254 	 * kHz, and all hosts must be able to pick a speed between 100
255 	 * kHz and 400 kHz.
256 	 *
257 	 * Once we know what the device can support, then we speed up.
258 	 */
259 	sda_init_clock(slot, 400000);
260 
261 	if ((rv = sda_init_ifcond(slot)) != SDA_EOK) {
262 		goto done;
263 	}
264 
265 	if (((rv = sda_init_sdio(slot)) != SDA_EOK) ||
266 	    ((rv = sda_init_sdmem(slot)) != SDA_EOK) ||
267 	    ((rv = sda_init_mmc(slot)) != SDA_EOK)) {
268 
269 		/* message will already have been logged */
270 		goto done;
271 	}
272 
273 	if ((slot->s_flags & (SLOTF_MEMORY | SLOTF_SDIO)) == 0) {
274 		sda_slot_err(slot, "Unidentified card type");
275 		rv = SDA_ENOTSUP;
276 		goto done;
277 	}
278 
279 	/*
280 	 * Memory cards need to obtain their CID before getting their RCA.
281 	 * This is a requirement for the state transitions... they go thru
282 	 * the ident state, unlike SDIO cards.
283 	 */
284 	if (slot->s_flags & SLOTF_MEMORY) {
285 		rv = sda_init_cmd(slot, CMD_BCAST_CID, 0, R2, slot->s_rcid);
286 		if (rv != SDA_EOK) {
287 			sda_slot_err(slot, "Failed getting card CID (%d)", rv);
288 			goto done;
289 		}
290 	}
291 
292 	if ((rv = sda_init_rca(slot)) != SDA_EOK) {
293 		goto done;
294 	}
295 
296 	slot->s_maxclk = 0xffffffffU;	/* special sentinel */
297 
298 	/*
299 	 * Figure out card supported bus width and speed.
300 	 *
301 	 * TODO: SDIO: For IO cards, we have to check what speed the card
302 	 * supports by looking in the CCCR_CAPAB register.  (SDIO cards
303 	 * can go low-speed only, full-speed, or high-speed.)
304 	 */
305 	if (slot->s_flags & SLOTF_MEMORY) {
306 
307 		/*
308 		 * We need to obtain the CSD.
309 		 */
310 		rv = sda_init_cmd(slot, CMD_SEND_CSD, slot->s_rca << 16, R2,
311 		    slot->s_rcsd);
312 		if (rv != 0) {
313 			sda_slot_err(slot, "Failed getting card CSD (%d)", rv);
314 			goto done;
315 		}
316 
317 		/*
318 		 * Calculate the maxclock.
319 		 */
320 		slot->s_maxclk = sda_mem_maxclk(slot);
321 	}
322 	if (((slot->s_flags & SLOTF_SDMEM) != 0) &&
323 	    ((slot->s_caps & SLOT_CAP_4BITS) != 0)) {
324 		slot->s_flags |= SLOTF_4BITS;
325 	}
326 	if (slot->s_flags & SLOTF_SDIO) {
327 		sda_slot_debug(slot, "Wide SDIO bus not yet supported");
328 		slot->s_flags &= ~SLOTF_4BITS;
329 	}
330 
331 	/*
332 	 * Now select the card.
333 	 */
334 	if ((rv = sda_init_cmd(slot, CMD_SELECT_CARD, slot->s_rca << 16,
335 	    R1b, &resp)) != SDA_EOK) {
336 		sda_slot_err(slot, "Failed selecting card (%d, %x)", rv, resp);
337 		goto done;
338 	}
339 
340 	if ((rv = sda_init_highspeed(slot)) != SDA_EOK) {
341 		goto done;
342 	}
343 
344 	sda_init_clock(slot, slot->s_maxclk);
345 
346 	/*
347 	 * Lets go to 4-bit bus mode, if possible.
348 	 */
349 	if ((rv = sda_init_width(slot)) != SDA_EOK) {
350 		goto done;
351 	}
352 
353 	if ((rv = sda_init_blocklen(slot)) != SDA_EOK) {
354 		goto done;
355 	}
356 
357 	/* note if a card is writable */
358 	if ((sda_getprop(slot, SDA_PROP_WPROTECT, &val) == SDA_EOK) &&
359 	    (val == 0)) {
360 		slot->s_flags |= SLOTF_WRITABLE;
361 	}
362 
363 	rv = SDA_EOK;
364 
365 done:
366 
367 	sda_slot_enter(slot);
368 	slot->s_init = B_FALSE;
369 	sda_slot_exit(slot);
370 
371 	sda_slot_wakeup(slot);
372 
373 	return (rv);
374 }
375 
376 sda_err_t
sda_init_blocklen(sda_slot_t * slot)377 sda_init_blocklen(sda_slot_t *slot)
378 {
379 	int		rv;
380 	uint32_t	resp;
381 
382 	if ((slot->s_flags & SLOTF_MEMORY) == 0)  {
383 		return (SDA_EOK);
384 	}
385 
386 	/*
387 	 * All memory cards support block sizes of 512.  Full stop.
388 	 */
389 	rv = sda_init_cmd(slot, CMD_SET_BLOCKLEN, 512, R1, &resp);
390 	if (rv != SDA_EOK) {
391 		sda_slot_err(slot, "Unable to set block length (%d, %x)",
392 		    rv, resp);
393 	}
394 	return (rv);
395 }
396 
397 void
sda_init_clock(sda_slot_t * slot,uint32_t hz)398 sda_init_clock(sda_slot_t *slot, uint32_t hz)
399 {
400 	int		rv;
401 	uint32_t	act;
402 
403 	/*
404 	 * Note that at no time is a failure programming the clock
405 	 * itself necessarily a fatal error.  Although if the clock
406 	 * wasn't programmed, other things will probably not work during
407 	 * initialization.
408 	 */
409 
410 	if ((rv = sda_setprop(slot, SDA_PROP_CLOCK, hz)) != SDA_EOK) {
411 		sda_slot_err(slot, "Failed setting clock to %u Hz (%d)",
412 		    hz, rv);
413 		/* XXX: FMA fail the slot */
414 		return;
415 	}
416 
417 	rv = sda_getprop(slot, SDA_PROP_CLOCK, &act);
418 	sda_slot_debug(slot,
419 	    rv == SDA_EOK ? "Clock set to %u Hz (requested %u Hz)" :
420 	    "Clock frequency unknown (good luck).", act, hz);
421 
422 	/*
423 	 * For now, just wait 10msec for clocks to stabilize to the
424 	 * card.  (Is this really necessary?)
425 	 */
426 	delay(drv_usectohz(10000));
427 }
428 
429 sda_err_t
sda_init_width(sda_slot_t * slot)430 sda_init_width(sda_slot_t *slot)
431 {
432 	int		rv;
433 	uint32_t	resp;
434 
435 	/*
436 	 * Spec says we should command the card first.
437 	 */
438 
439 	rv = sda_setprop(slot, SDA_PROP_BUSWIDTH, 1);
440 	if (rv != SDA_EOK) {
441 		sda_slot_err(slot, "Unable to set slot 1-bit mode (%d)", rv);
442 		return (rv);
443 	}
444 
445 	if ((slot->s_flags & SLOTF_4BITS) == 0) {
446 		return (SDA_EOK);
447 	}
448 
449 	/*
450 	 * TODO: SDIO: SDIO cards set the CCCR_BUS_WIDTH
451 	 * and CCCR_CD_DISABLE bits here.
452 	 */
453 
454 	/*
455 	 * If we're going to use all 4 pins, we really need to disconnect
456 	 * the card pullup resistor.   A consquence of this, is that hosts
457 	 * which use that resistor for detection must not claim to support
458 	 * 4-bit bus mode.  This is a limitation of our implementation.
459 	 */
460 	rv = sda_init_acmd(slot, ACMD_SET_CLR_CARD_DETECT, 1, R1, &resp);
461 	if (rv != SDA_EOK) {
462 		sda_slot_err(slot,
463 		    "Unable disconnect DAT3 resistor on card (%d, %x)",
464 		    rv, resp);
465 		/* non-fatal error, muddle on */
466 		return (SDA_EOK);
467 	}
468 
469 	rv = sda_init_acmd(slot, ACMD_SET_BUS_WIDTH, 2, R1, &resp);
470 	if (rv != SDA_EOK) {
471 		sda_slot_err(slot, "Unable to set card 4-bit mode (%d, %x)",
472 		    rv, resp);
473 		/* non-fatal error, muddle on */
474 		return (SDA_EOK);
475 	}
476 
477 	rv = sda_setprop(slot, SDA_PROP_BUSWIDTH, 4);
478 	if (rv != SDA_EOK) {
479 		/*
480 		 * This is bad news.  We've already asked for the card to
481 		 * to use 4-bit mode, but the host is not complying.  It
482 		 * shouldn't ever happen, so we just error out.
483 		 */
484 		sda_slot_err(slot, "Unable to set slot 4-bit mode (%d)", rv);
485 	}
486 
487 	return (rv);
488 }
489 
490 sda_err_t
sda_init_ifcond(sda_slot_t * slot)491 sda_init_ifcond(sda_slot_t *slot)
492 {
493 	int		rv;
494 	int		tries;
495 	uint32_t	vchk;
496 	uint32_t	resp;
497 
498 	/*
499 	 * Try SEND_IF_COND.  Note that this assumes that the host is
500 	 * supplying 2.7 - 3.6 voltage range.  The standard is not
501 	 * defined for any other ranges.
502 	 */
503 	vchk = R7_VHS_27_36V | R7_PATTERN;
504 
505 	/* we try this a few times, just to be sure */
506 	for (tries = 0; tries < 5; tries++) {
507 		rv = sda_init_cmd(slot, CMD_GO_IDLE, 0, R0, NULL);
508 		if (rv != SDA_EOK) {
509 			sda_slot_err(slot, "Failed to IDLE card");
510 			return (rv);
511 		}
512 
513 		rv = sda_init_cmd(slot, CMD_SEND_IF_COND, vchk, R7, &resp);
514 		if (rv == SDA_EOK) {
515 			break;
516 		}
517 		delay(drv_usectohz(10000));
518 	}
519 
520 	if (rv != SDA_EOK) {
521 		(void) sda_init_cmd(slot, CMD_GO_IDLE, 0, R0, NULL);
522 		slot->s_flags &= ~SLOTF_IFCOND;
523 
524 	} else if (resp != vchk) {
525 		sda_slot_err(slot, "Card voltages incompatible! (%x)", resp);
526 		return (SDA_ENOTSUP);
527 
528 	} else {
529 		/* SDHC compliant */
530 		slot->s_flags |= SLOTF_IFCOND;
531 	}
532 
533 	return (SDA_EOK);
534 }
535 
536 sda_err_t
sda_init_rca(sda_slot_t * slot)537 sda_init_rca(sda_slot_t *slot)
538 {
539 	int		rv;
540 	int		tries;
541 	uint32_t	resp;
542 
543 	/*
544 	 * Program the RCA.  Note that MMC has a different mechanism
545 	 * for this.
546 	 */
547 	for (tries = 0; tries < 10; tries++) {
548 
549 		if (slot->s_flags & SLOTF_MMC) {
550 			/*
551 			 * For MMC, we push the RCA to the MMC.  We
552 			 * arbitrarily start at 0x100, and add from
553 			 * there.
554 			 */
555 			rv = sda_init_cmd(slot, CMD_SEND_RCA,
556 			    (0x100 + tries) << 16, R1, NULL);
557 			if (rv == SDA_EOK)
558 				slot->s_rca = 0x100 + tries;
559 		} else {
560 			/*
561 			 * For SDcard, we are basically asking the
562 			 * card to propose a value.  It *may* propose
563 			 * a value of zero, in which case we will have
564 			 * to ask again.
565 			 */
566 			rv = sda_init_cmd(slot, CMD_SEND_RCA, 0, R6, &resp);
567 			if (rv == SDA_EOK)
568 				slot->s_rca = resp >> 16;
569 		}
570 		if ((rv == SDA_EOK) && (slot->s_rca != 0)) {
571 			sda_slot_debug(slot, "Relative address (RCA) = %d",
572 			    slot->s_rca);
573 			return (SDA_EOK);
574 		}
575 	}
576 
577 	sda_slot_err(slot, "Unable to negotiate a suitable RCA (%d)", rv);
578 	return ((rv != SDA_EOK) ? rv : SDA_EINVAL);
579 }
580 
581 sda_err_t
sda_init_switch(sda_slot_t * slot,uint8_t mode,uint8_t grp,uint8_t val,uint8_t * data)582 sda_init_switch(sda_slot_t *slot, uint8_t mode, uint8_t grp, uint8_t val,
583     uint8_t *data)
584 {
585 	sda_cmd_t	*cmdp;
586 	sda_err_t	errno;
587 	uint32_t	arg;
588 
589 	/*
590 	 * The spec says we should leave unselected groups set to 0xf,
591 	 * to prevent inadvertent changes.
592 	 */
593 	arg = (mode << 31) | 0xffffff;
594 	arg &= ~(0xf << (grp << 2));
595 	arg |= (val << (grp << 2));
596 
597 	cmdp = sda_cmd_alloc(slot, CMD_SWITCH_FUNC, arg, R1, NULL, KM_SLEEP);
598 
599 	cmdp->sc_flags |= SDA_CMDF_INIT | SDA_CMDF_DAT | SDA_CMDF_READ;
600 	cmdp->sc_blksz = 64;
601 	cmdp->sc_nblks = 1;
602 	cmdp->sc_kvaddr = (void *)data;
603 
604 	errno = sda_cmd_exec(slot, cmdp, NULL);
605 
606 	sda_cmd_free(cmdp);
607 
608 	return (errno);
609 
610 }
611 
612 sda_err_t
sda_init_highspeed(sda_slot_t * slot)613 sda_init_highspeed(sda_slot_t *slot)
614 {
615 	uint32_t	ccc;
616 	uint8_t		data[64];
617 	sda_err_t	rv;
618 
619 	if ((slot->s_caps & SLOT_CAP_HISPEED) == 0) {
620 		return (SDA_EOK);
621 	}
622 	if ((slot->s_flags & SLOTF_SDMEM) == 0) {
623 		return (SDA_EOK);
624 	}
625 	ccc = sda_mem_getbits(slot->s_rcsd, 95, 12);
626 	if ((ccc & (1 << 10)) == 0) {
627 		return (SDA_EOK);
628 	}
629 
630 	rv = sda_init_switch(slot, 0, 0, 1, data);
631 
632 	/* these are big-endian bits, bit 401 */
633 	if ((rv != SDA_EOK) || ((data[13] & (1 << 1)) == 0)) {
634 		return (SDA_EOK);
635 	}
636 
637 	rv = sda_init_switch(slot, 1, 0, 1, data);
638 	if (rv != SDA_EOK) {
639 		return (SDA_EOK);
640 	}
641 
642 	/* now program the card */
643 	rv = sda_setprop(slot, SDA_PROP_HISPEED, 1);
644 	if (rv != SDA_EOK) {
645 		sda_slot_err(slot, "Failed setting slot to high speed mode");
646 	} else {
647 		/* the card should now support 50 MHz */
648 		slot->s_maxclk = 50000000;
649 	}
650 
651 	return (rv);
652 }
653