1 /******************************************************************************
2 *
3 * Copyright(c) 2019 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15
16 #include "mac_ax.h"
17
18 #define CHIP_ID_HW_DEF_8852A 0x50
19 #define CHIP_ID_HW_DEF_8852B 0x51
20 #define CHIP_ID_HW_DEF_8852C 0x52
21 #define CHIP_ID_HW_DEF_8192XB 0x53
22
23 #define SDIO_WAIT_CNT 50
24 #if MAC_AX_SDIO_SUPPORT
25 static u8 r8_indir_cmd52_sdio(void *drv_adapter,
26 struct mac_ax_pltfm_cb *pltfm_cb, u32 adr);
27 #endif
28
29 #ifndef CONFIG_NEW_HALMAC_INTERFACE
chk_pltfm_cb(void * drv_adapter,enum mac_ax_intf intf,struct mac_ax_pltfm_cb * pltfm_cb)30 static u8 chk_pltfm_cb(void *drv_adapter, enum mac_ax_intf intf,
31 struct mac_ax_pltfm_cb *pltfm_cb)
32 {
33 if (!pltfm_cb)
34 return MACSUCCESS;
35
36 if (!pltfm_cb->msg_print)
37 return MACSUCCESS;
38
39 #if MAC_AX_SDIO_SUPPORT
40 if (!pltfm_cb->sdio_cmd52_r8 || !pltfm_cb->sdio_cmd53_r8 ||
41 !pltfm_cb->sdio_cmd53_r16 || !pltfm_cb->sdio_cmd53_r32 ||
42 !pltfm_cb->sdio_cmd53_rn || !pltfm_cb->sdio_cmd52_w8 ||
43 !pltfm_cb->sdio_cmd53_w8 || !pltfm_cb->sdio_cmd53_w16 ||
44 !pltfm_cb->sdio_cmd53_w32 || !pltfm_cb->sdio_cmd53_wn ||
45 !pltfm_cb->sdio_cmd52_cia_r8) {
46 pltfm_cb->msg_print(drv_adapter, _PHL_ERR_, "[ERR]CB-SDIO\n");
47 return MACSUCCESS;
48 }
49 #endif
50
51 #if (MAC_AX_USB_SUPPORT || MAC_AX_PCIE_SUPPORT)
52 if (!pltfm_cb->reg_r8 || !pltfm_cb->reg_r16 ||
53 !pltfm_cb->reg_r32 || !pltfm_cb->reg_w8 ||
54 !pltfm_cb->reg_w16 || !pltfm_cb->reg_w32) {
55 pltfm_cb->msg_print(drv_adapter, _PHL_ERR_, "[ERR]CB-USB or PCIE\n");
56 return MACSUCCESS;
57 }
58 #endif
59 if (!pltfm_cb->rtl_free || !pltfm_cb->rtl_malloc ||
60 !pltfm_cb->rtl_memcpy || !pltfm_cb->rtl_memset ||
61 !pltfm_cb->rtl_delay_us || !pltfm_cb->rtl_delay_ms ||
62 !pltfm_cb->rtl_mutex_init || !pltfm_cb->rtl_mutex_deinit ||
63 !pltfm_cb->rtl_mutex_lock || !pltfm_cb->rtl_mutex_unlock ||
64 !pltfm_cb->event_notify) {
65 pltfm_cb->msg_print(drv_adapter, _PHL_ERR_, "[ERR]CB-OS\n");
66 return MACSUCCESS;
67 }
68
69 return MACPFCB;
70 }
71 #endif /*CONFIG_NEW_HALMAC_INTERFACE*/
72
chk_pltfm_endian(void)73 static u8 chk_pltfm_endian(void)
74 {
75 u32 num = 1;
76 u8 *num_ptr = (u8 *)#
77
78 if (*num_ptr != PLATFOM_IS_LITTLE_ENDIAN)
79 return MACSUCCESS;
80
81 return MACPFCB;
82 }
83
84 #ifdef CONFIG_NEW_HALMAC_INTERFACE
85 #if MAC_AX_SDIO_SUPPORT
r8_indir_cmd52_sdio(void * drv_adapter,struct mac_ax_pltfm_cb * pltfm_cb,u32 adr)86 static u8 r8_indir_cmd52_sdio(void *drv_adapter,
87 struct mac_ax_pltfm_cb *pltfm_cb, u32 adr)
88 {
89 u8 tmp;
90 u32 cnt;
91
92 PLTFM_SDIO_CMD52_W8(R_AX_SDIO_INDIRECT_ADDR, (u8)adr);
93 PLTFM_SDIO_CMD52_W8(R_AX_SDIO_INDIRECT_ADDR + 1, (u8)(adr >> 8));
94 PLTFM_SDIO_CMD52_W8(R_AX_SDIO_INDIRECT_ADDR + 2, (u8)(adr >> 16));
95 PLTFM_SDIO_CMD52_W8(R_AX_SDIO_INDIRECT_ADDR + 3,
96 (u8)((adr | B_AX_INDIRECT_RDY) >> 24));
97 PLTFM_SDIO_CMD52_W8(R_AX_SDIO_INDIRECT_CTRL, (u8)B_AX_INDIRECT_REG_R);
98
99 cnt = SDIO_WAIT_CNT;
100 do {
101 tmp = PLTFM_SDIO_CMD52_R8(R_AX_SDIO_INDIRECT_ADDR + 3);
102 cnt--;
103 } while (((tmp & BIT(7)) == 0) && (cnt > 0));
104
105 if (((tmp & BIT(7)) == 0) && cnt == 0)
106 PLTFM_MSG_ERR("[ERR]sdio indirect CMD52 read\n");
107
108 return PLTFM_SDIO_CMD52_R8(R_AX_SDIO_INDIRECT_DATA);
109 }
110 #endif
get_chip_info(struct mac_ax_adapter * adapter,struct mac_ax_pltfm_cb * pltfm_cb,enum mac_ax_intf intf,u8 * id,u8 * cv)111 static u32 get_chip_info(struct mac_ax_adapter *adapter,
112 struct mac_ax_pltfm_cb *pltfm_cb,
113 enum mac_ax_intf intf, u8 *id, u8 *cv)
114 {
115 u32 cv_temp;
116 u8 cur_id;
117
118 if (!cv || !id)
119 return MACNPTR;
120
121 switch (intf) {
122 #if MAC_AX_SDIO_SUPPORT
123 case MAC_AX_INTF_SDIO:
124 cur_id = r8_indir_cmd52_sdio(adapter, R_AX_SYS_CHIPINFO);
125 *cv = r8_indir_cmd52_sdio(adapter, R_AX_SYS_CFG1 + 1) >> 4;
126 break;
127 #endif
128 #if (MAC_AX_USB_SUPPORT || MAC_AX_PCIE_SUPPORT)
129 case MAC_AX_INTF_USB:
130 case MAC_AX_INTF_PCIE:
131 cur_id = PLTFM_REG_R8(R_AX_SYS_CHIPINFO);
132 *cv = PLTFM_REG_R8(R_AX_SYS_CFG1 + 1) >> 4;
133
134 if (cur_id == CHIP_ID_HW_DEF_8852A) {
135 if (*cv <= CBV) {
136 cv_temp = PLTFM_REG_R32(R_AX_GPIO0_7_FUNC_SEL);
137 if (cv_temp == 0xdeadbeef)
138 *cv = CAV;
139 else
140 *cv = CBV;
141 }
142 }
143 break;
144 #endif
145 default:
146 return MACINTF;
147 }
148
149 switch (cur_id) {
150 case CHIP_ID_HW_DEF_8852A:
151 *id = MAC_AX_CHIP_ID_8852A;
152 break;
153 case CHIP_ID_HW_DEF_8852B:
154 *id = MAC_AX_CHIP_ID_8852B;
155 break;
156 case CHIP_ID_HW_DEF_8852C:
157 *id = MAC_AX_CHIP_ID_8852C;
158 break;
159 default:
160 return MACCHIPID;
161 }
162
163 return MACSUCCESS;
164 }
165
mac_ax_ops_init_v1(void * phl_adapter,void * drv_adapter,enum rtw_chip_id chip_id,enum rtw_hci_type hci,struct mac_ax_adapter ** mac_adapter,struct mac_ax_ops ** mac_ops)166 u32 mac_ax_ops_init_v1(void *phl_adapter, void *drv_adapter,
167 enum rtw_chip_id chip_id,
168 enum rtw_hci_type hci,
169 struct mac_ax_adapter **mac_adapter,
170 struct mac_ax_ops **mac_ops)
171 {
172 u32 ret;
173 u8 cv;
174 struct mac_ax_adapter *adapter;
175 enum mac_ax_intf intf = MAC_AX_INTF_INVALID;
176
177 if (!chk_pltfm_endian())
178 return MACPFED;
179
180 ret = 0;
181
182 if (hci == RTW_HCI_PCIE)
183 intf = MAC_AX_INTF_PCIE;
184 else if (hci == RTW_HCI_USB)
185 intf = MAC_AX_INTF_USB;
186 else if (hci == RTW_HCI_SDIO)
187 intf = MAC_AX_INTF_SDIO;
188
189 ret = get_chip_info(drv_adapter, NULL, intf, &chip_id, &cv);
190 if (ret)
191 return ret;
192
193 adapter = get_mac_ax_adapter(intf, chip_id, cv, phl_adapter,
194 drv_adapter, NULL);
195 if (!adapter) {
196 PLTFM_MSG_PRINT("[ERR]Get MAC adapter\n");
197 return MACADAPTER;
198 }
199 PLTFM_MSG_ALWAYS("MAC_AX_MAJOR_VER = %d\n"
200 "MAC_AX_PROTOTYPE_VER = %d\n"
201 "MAC_AX_SUB_VER = %d\n"
202 "MAC_AX_SUB_INDEX = %d\n",
203 MAC_AX_MAJOR_VER, MAC_AX_PROTOTYPE_VER,
204 MAC_AX_SUB_VER, MAC_AX_SUB_INDEX);
205
206 *mac_adapter = adapter;
207 *mac_ops = adapter->ops;
208
209 return MACSUCCESS;
210 }
211
212 #else
213
214 #if MAC_AX_SDIO_SUPPORT
r8_indir_cmd52_sdio(void * drv_adapter,struct mac_ax_pltfm_cb * pltfm_cb,u32 adr)215 static u8 r8_indir_cmd52_sdio(void *drv_adapter,
216 struct mac_ax_pltfm_cb *pltfm_cb, u32 adr)
217 {
218 u8 tmp;
219 u32 cnt;
220
221 pltfm_cb->sdio_cmd52_w8(drv_adapter, R_AX_SDIO_INDIRECT_ADDR,
222 (u8)adr);
223 pltfm_cb->sdio_cmd52_w8(drv_adapter, R_AX_SDIO_INDIRECT_ADDR + 1,
224 (u8)(adr >> 8));
225 pltfm_cb->sdio_cmd52_w8(drv_adapter, R_AX_SDIO_INDIRECT_ADDR + 2,
226 (u8)(adr >> 16));
227 pltfm_cb->sdio_cmd52_w8(drv_adapter, R_AX_SDIO_INDIRECT_ADDR + 3,
228 (u8)((adr | B_AX_INDIRECT_RDY) >> 24));
229 pltfm_cb->sdio_cmd52_w8(drv_adapter, R_AX_SDIO_INDIRECT_CTRL,
230 (u8)B_AX_INDIRECT_REG_R);
231
232 cnt = SDIO_WAIT_CNT;
233 do {
234 tmp = pltfm_cb->sdio_cmd52_r8(drv_adapter,
235 R_AX_SDIO_INDIRECT_ADDR + 3);
236 cnt--;
237 } while (((tmp & BIT(7)) == 0) && (cnt > 0));
238
239 if (((tmp & BIT(7)) == 0) && cnt == 0)
240 pltfm_cb->msg_print(drv_adapter, _PHL_ERR_,
241 "[ERR]sdio indirect CMD52 read\n");
242
243 return pltfm_cb->sdio_cmd52_r8(drv_adapter, R_AX_SDIO_INDIRECT_DATA);
244 }
245 #endif
get_chip_info(void * drv_adapter,struct mac_ax_pltfm_cb * pltfm_cb,enum mac_ax_intf intf,u8 * id,u8 * cv)246 static u32 get_chip_info(void *drv_adapter, struct mac_ax_pltfm_cb *pltfm_cb,
247 enum mac_ax_intf intf, u8 *id, u8 *cv)
248 {
249 u8 cur_id;
250
251 if (!cv || !id)
252 return MACNPTR;
253
254 switch (intf) {
255 #if MAC_AX_SDIO_SUPPORT
256 case MAC_AX_INTF_SDIO:
257 cur_id = r8_indir_cmd52_sdio(drv_adapter, pltfm_cb,
258 R_AX_SYS_CHIPINFO);
259 *cv = r8_indir_cmd52_sdio(drv_adapter, pltfm_cb,
260 R_AX_SYS_CFG1 + 1) >> 4;
261 if (cur_id == CHIP_ID_HW_DEF_8852A)
262 if (*cv <= CBV)
263 *cv = CBV;
264
265 break;
266 #endif
267 #if (MAC_AX_USB_SUPPORT || MAC_AX_PCIE_SUPPORT)
268 case MAC_AX_INTF_USB:
269 case MAC_AX_INTF_PCIE:
270 cur_id = pltfm_cb->reg_r8(drv_adapter, R_AX_SYS_CHIPINFO);
271 *cv = pltfm_cb->reg_r8(drv_adapter, R_AX_SYS_CFG1 + 1) >> 4;
272 if (cur_id == CHIP_ID_HW_DEF_8852A)
273 if (*cv <= CBV)
274 *cv = CBV;
275
276 break;
277 #endif
278 default:
279 return MACINTF;
280 }
281
282 switch (cur_id) {
283 case CHIP_ID_HW_DEF_8852A:
284 *id = MAC_AX_CHIP_ID_8852A;
285 break;
286 case CHIP_ID_HW_DEF_8852B:
287 *id = MAC_AX_CHIP_ID_8852B;
288 break;
289 case CHIP_ID_HW_DEF_8852C:
290 *id = MAC_AX_CHIP_ID_8852C;
291 break;
292 case CHIP_ID_HW_DEF_8192XB:
293 *id = MAC_AX_CHIP_ID_8192XB;
294 break;
295 default:
296 return MACCHIPID;
297 }
298
299 return MACSUCCESS;
300 }
301
mac_ax_ops_init(void * drv_adapter,struct mac_ax_pltfm_cb * pltfm_cb,enum mac_ax_intf intf,struct mac_ax_adapter ** mac_adapter,struct mac_ax_ops ** mac_ops)302 u32 mac_ax_ops_init(void *drv_adapter, struct mac_ax_pltfm_cb *pltfm_cb,
303 enum mac_ax_intf intf,
304 struct mac_ax_adapter **mac_adapter,
305 struct mac_ax_ops **mac_ops)
306 {
307 u32 ret;
308 u8 chip_id = 0;
309 u8 cv = 0;
310 struct mac_ax_adapter *adapter;
311
312 if (!chk_pltfm_cb(drv_adapter, intf, pltfm_cb))
313 return MACPFCB;
314
315 if (!chk_pltfm_endian())
316 return MACPFED;
317
318 pltfm_cb->msg_print(drv_adapter, _PHL_ERR_,
319 "MAC_AX_MAJOR_VER = %d\n"
320 "MAC_AX_PROTOTYPE_VER = %d\n"
321 "MAC_AX_SUB_VER = %d\n"
322 "MAC_AX_SUB_INDEX = %d\n",
323 MAC_AX_MAJOR_VER, MAC_AX_PROTOTYPE_VER,
324 MAC_AX_SUB_VER, MAC_AX_SUB_INDEX);
325
326 ret = get_chip_info(drv_adapter, pltfm_cb, intf, &chip_id, &cv);
327 if (ret)
328 return ret;
329
330 adapter = get_mac_ax_adapter(intf, chip_id, cv, drv_adapter,
331 pltfm_cb);
332 if (!adapter) {
333 pltfm_cb->msg_print(drv_adapter, _PHL_ERR_, "[ERR]Get MAC adapter\n");
334 return MACADAPTER;
335 }
336
337 *mac_adapter = adapter;
338 *mac_ops = adapter->ops;
339
340 #if MAC_AX_FEATURE_HV
341 adapter->hv_ops = get_hv_ax_ops(adapter);
342 #endif
343
344 #if MAC_AX_PHL_H2C
345
346 #else
347 ret = h2cb_init(adapter);
348 if (ret != MACSUCCESS) {
349 PLTFM_MSG_ERR("[ERR]h2cb init %d\n", ret);
350 return ret;
351 }
352 #endif
353
354 ret = role_tbl_init(adapter);
355 if (ret != MACSUCCESS) {
356 PLTFM_MSG_ERR("[ERR]role tbl init %d\n", ret);
357 return ret;
358 }
359
360 ret = sec_info_tbl_init(adapter, SEC_CAM_NORMAL);
361 if (ret != MACSUCCESS) {
362 PLTFM_MSG_ERR("[ERR]sec info tbl init %d\n", ret);
363 return ret;
364 }
365
366 ret = efuse_tbl_init(adapter);
367 if (ret != MACSUCCESS) {
368 PLTFM_MSG_ERR("[ERR]efuse tbl init %d\n", ret);
369 return ret;
370 }
371
372 ret = p2p_info_init(adapter);
373 if (ret != MACSUCCESS) {
374 PLTFM_MSG_ERR("[ERR]p2p info init %d\n", ret);
375 return ret;
376 }
377
378 ret = mport_info_init(adapter);
379 if (ret != MACSUCCESS) {
380 PLTFM_MSG_ERR("[ERR]mpinfo info init %d\n", ret);
381 return ret;
382 }
383
384 ret = mix_info_init(adapter);
385 if (ret != MACSUCCESS) {
386 PLTFM_MSG_ERR("[ERR]mix info init %d\n", ret);
387 return ret;
388 }
389
390 #if MAC_AX_SDIO_SUPPORT
391 ret = sdio_tbl_init(adapter);
392 if (ret != MACSUCCESS) {
393 PLTFM_MSG_ERR("[ERR]sdio tbl init %d\n", ret);
394 return ret;
395 }
396 #endif
397
398 ret = hfc_info_init(adapter);
399 if (ret != MACSUCCESS) {
400 PLTFM_MSG_ERR("[ERR]hfc info init %d\n", ret);
401 return ret;
402 }
403
404 ret = dbcc_info_init(adapter);
405 if (ret != MACSUCCESS) {
406 PLTFM_MSG_ERR("[ERR]dbcc info init %d\n", ret);
407 return ret;
408 }
409
410 return MACSUCCESS;
411 }
412 #endif /*CONFIG_NEW_HALMAC_INTERFACE*/
413
414 #if MAC_AX_PHL_H2C
mac_ax_phl_init(void * phl_adapter,struct mac_ax_adapter * mac_adapter)415 u32 mac_ax_phl_init(void *phl_adapter, struct mac_ax_adapter *mac_adapter)
416 {
417 struct mac_ax_adapter *adapter = mac_adapter;
418
419 adapter->phl_adapter = phl_adapter;
420
421 return MACSUCCESS;
422 }
423 #endif
mac_ax_ops_exit(struct mac_ax_adapter * adapter)424 u32 mac_ax_ops_exit(struct mac_ax_adapter *adapter)
425 {
426 u32 ret;
427 struct mac_ax_efuse_param *efuse_param = &adapter->efuse_param;
428 struct scan_chinfo_list *scan_list;
429
430 ret = h2cb_exit(adapter);
431 if (ret != MACSUCCESS) {
432 PLTFM_MSG_ERR("[ERR]h2c buffer exit %d\n", ret);
433 return ret;
434 }
435
436 ret = free_sec_info_tbl(adapter, SEC_CAM_NORMAL);
437 if (ret != MACSUCCESS) {
438 PLTFM_MSG_ERR("[ERR]sec table exit %d\n", ret);
439 return ret;
440 }
441
442 ret = role_tbl_exit(adapter);
443 if (ret != MACSUCCESS) {
444 PLTFM_MSG_ERR("[ERR]role table exit %d\n", ret);
445 return ret;
446 }
447
448 ret = efuse_tbl_exit(adapter);
449 if (ret != MACSUCCESS) {
450 PLTFM_MSG_ERR("[ERR]efuse table exit %d\n", ret);
451 return ret;
452 }
453
454 ret = p2p_info_exit(adapter);
455 if (ret != MACSUCCESS) {
456 PLTFM_MSG_ERR("[ERR]p2p info exit %d\n", ret);
457 return ret;
458 }
459
460 ret = mport_info_exit(adapter);
461 if (ret != MACSUCCESS) {
462 PLTFM_MSG_ERR("[ERR]mpinfo info exit %d\n", ret);
463 return ret;
464 }
465
466 ret = mix_info_exit(adapter);
467 if (ret != MACSUCCESS) {
468 PLTFM_MSG_ERR("[ERR]mix info exit %d\n", ret);
469 return ret;
470 }
471
472 #if MAC_AX_SDIO_SUPPORT
473 ret = sdio_tbl_exit(adapter);
474 if (ret != MACSUCCESS) {
475 PLTFM_MSG_ERR("[ERR]efuse table exit %d\n", ret);
476 return ret;
477 }
478 #endif
479
480 ret = hfc_info_exit(adapter);
481 if (ret != MACSUCCESS) {
482 PLTFM_MSG_ERR("[ERR]hfc info exit %d\n", ret);
483 return ret;
484 }
485
486 ret = free_aoac_report(adapter);
487 if (ret != MACSUCCESS) {
488 PLTFM_MSG_ERR("[ERR]free aoac report %d\n", ret);
489 return ret;
490 }
491
492 ret = dbcc_info_exit(adapter);
493 if (ret != MACSUCCESS) {
494 PLTFM_MSG_ERR("[ERR]dbcc info exit %d\n", ret);
495 return ret;
496 }
497
498 if (efuse_param->efuse_map) {
499 PLTFM_FREE(efuse_param->efuse_map,
500 adapter->hw_info->efuse_size);
501 efuse_param->efuse_map = (u8 *)NULL;
502 }
503
504 if (efuse_param->bt_efuse_map) {
505 PLTFM_FREE(efuse_param->bt_efuse_map,
506 adapter->hw_info->bt_efuse_size);
507 efuse_param->bt_efuse_map = (u8 *)NULL;
508 }
509
510 if (efuse_param->log_efuse_map) {
511 PLTFM_FREE(efuse_param->log_efuse_map,
512 adapter->hw_info->log_efuse_size);
513 efuse_param->log_efuse_map = (u8 *)NULL;
514 }
515
516 if (efuse_param->bt_log_efuse_map) {
517 PLTFM_FREE(efuse_param->bt_log_efuse_map,
518 adapter->hw_info->bt_log_efuse_size);
519 efuse_param->bt_log_efuse_map = (u8 *)NULL;
520 }
521
522 if (efuse_param->dav_efuse_map) {
523 PLTFM_FREE(efuse_param->dav_efuse_map,
524 adapter->hw_info->dav_efuse_size);
525 efuse_param->dav_efuse_map = (u8 *)NULL;
526 }
527
528 if (efuse_param->dav_log_efuse_map) {
529 PLTFM_FREE(efuse_param->dav_log_efuse_map,
530 adapter->hw_info->dav_log_efuse_size);
531 efuse_param->dav_log_efuse_map = (u8 *)NULL;
532 }
533
534 scan_list = adapter->scanofld_info.list;
535 if (scan_list) {
536 mac_scanofld_ch_list_clear(adapter, scan_list);
537 PLTFM_FREE((u8 *)scan_list, sizeof(struct scan_chinfo_list));
538 adapter->scanofld_info.list = NULL;
539 }
540
541 PLTFM_FREE(adapter->hw_info, sizeof(struct mac_ax_hw_info));
542
543 PLTFM_FREE(adapter, sizeof(struct mac_ax_adapter));
544 return MACSUCCESS;
545 }
546
is_chip_id(struct mac_ax_adapter * adapter,enum mac_ax_chip_id id)547 u32 is_chip_id(struct mac_ax_adapter *adapter, enum mac_ax_chip_id id)
548 {
549 return (id == adapter->hw_info->chip_id ? 1 : 0);
550 }
551
is_cv(struct mac_ax_adapter * adapter,enum rtw_cv cv)552 u32 is_cv(struct mac_ax_adapter *adapter, enum rtw_cv cv)
553 {
554 return (cv == adapter->hw_info->cv ? 1 : 0);
555 }
556
557