bus.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2014 Google, Inc
  4. */
  5. #include <common.h>
  6. #ifdef CONFIG_SANDBOX
  7. #include <os.h>
  8. #endif
  9. #include <dm.h>
  10. #include <dm/device.h>
  11. #include <dm/device-internal.h>
  12. #include <dm/test.h>
  13. #include <dm/uclass-internal.h>
  14. #include <dm/util.h>
  15. #include <test/ut.h>
  16. DECLARE_GLOBAL_DATA_PTR;
  17. struct dm_test_parent_platdata {
  18. int count;
  19. int bind_flag;
  20. int uclass_bind_flag;
  21. };
  22. enum {
  23. FLAG_CHILD_PROBED = 10,
  24. FLAG_CHILD_REMOVED = -7,
  25. };
  26. static struct dm_test_state *test_state;
  27. static int testbus_drv_probe(struct udevice *dev)
  28. {
  29. return dm_scan_fdt_dev(dev);
  30. }
  31. static int testbus_child_post_bind(struct udevice *dev)
  32. {
  33. struct dm_test_parent_platdata *plat;
  34. plat = dev_get_parent_platdata(dev);
  35. plat->bind_flag = 1;
  36. plat->uclass_bind_flag = 2;
  37. return 0;
  38. }
  39. static int testbus_child_pre_probe(struct udevice *dev)
  40. {
  41. struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev);
  42. parent_data->flag += FLAG_CHILD_PROBED;
  43. return 0;
  44. }
  45. static int testbus_child_pre_probe_uclass(struct udevice *dev)
  46. {
  47. struct dm_test_priv *priv = dev_get_priv(dev);
  48. priv->uclass_flag++;
  49. return 0;
  50. }
  51. static int testbus_child_post_probe_uclass(struct udevice *dev)
  52. {
  53. struct dm_test_priv *priv = dev_get_priv(dev);
  54. priv->uclass_postp++;
  55. return 0;
  56. }
  57. static int testbus_child_post_remove(struct udevice *dev)
  58. {
  59. struct dm_test_parent_data *parent_data = dev_get_parent_priv(dev);
  60. struct dm_test_state *dms = test_state;
  61. parent_data->flag += FLAG_CHILD_REMOVED;
  62. if (dms)
  63. dms->removed = dev;
  64. return 0;
  65. }
  66. static const struct udevice_id testbus_ids[] = {
  67. {
  68. .compatible = "denx,u-boot-test-bus",
  69. .data = DM_TEST_TYPE_FIRST },
  70. { }
  71. };
  72. U_BOOT_DRIVER(testbus_drv) = {
  73. .name = "testbus_drv",
  74. .of_match = testbus_ids,
  75. .id = UCLASS_TEST_BUS,
  76. .probe = testbus_drv_probe,
  77. .child_post_bind = testbus_child_post_bind,
  78. .priv_auto_alloc_size = sizeof(struct dm_test_priv),
  79. .platdata_auto_alloc_size = sizeof(struct dm_test_pdata),
  80. .per_child_auto_alloc_size = sizeof(struct dm_test_parent_data),
  81. .per_child_platdata_auto_alloc_size =
  82. sizeof(struct dm_test_parent_platdata),
  83. .child_pre_probe = testbus_child_pre_probe,
  84. .child_post_remove = testbus_child_post_remove,
  85. };
  86. UCLASS_DRIVER(testbus) = {
  87. .name = "testbus",
  88. .id = UCLASS_TEST_BUS,
  89. .flags = DM_UC_FLAG_SEQ_ALIAS,
  90. .child_pre_probe = testbus_child_pre_probe_uclass,
  91. .child_post_probe = testbus_child_post_probe_uclass,
  92. };
  93. /* Test that we can probe for children */
  94. static int dm_test_bus_children(struct unit_test_state *uts)
  95. {
  96. int num_devices = 8;
  97. struct udevice *bus;
  98. struct uclass *uc;
  99. ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
  100. ut_asserteq(num_devices, list_count_items(&uc->dev_head));
  101. /* Probe the bus, which should yield 3 more devices */
  102. ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
  103. num_devices += 3;
  104. ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
  105. ut_asserteq(num_devices, list_count_items(&uc->dev_head));
  106. ut_assert(!dm_check_devices(uts, num_devices));
  107. return 0;
  108. }
  109. DM_TEST(dm_test_bus_children, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  110. /* Test our functions for accessing children */
  111. static int dm_test_bus_children_funcs(struct unit_test_state *uts)
  112. {
  113. const void *blob = gd->fdt_blob;
  114. struct udevice *bus, *dev;
  115. int node;
  116. ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
  117. /* device_get_child() */
  118. ut_assertok(device_get_child(bus, 0, &dev));
  119. ut_asserteq(-ENODEV, device_get_child(bus, 4, &dev));
  120. ut_assertok(device_get_child_by_seq(bus, 5, &dev));
  121. ut_assert(dev->flags & DM_FLAG_ACTIVATED);
  122. ut_asserteq_str("c-test@5", dev->name);
  123. /* Device with sequence number 0 should be accessible */
  124. ut_asserteq(-ENODEV, device_find_child_by_seq(bus, -1, true, &dev));
  125. ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
  126. ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
  127. ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 0, false, &dev));
  128. ut_assertok(device_get_child_by_seq(bus, 0, &dev));
  129. ut_assert(dev->flags & DM_FLAG_ACTIVATED);
  130. /* There is no device with sequence number 2 */
  131. ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, false, &dev));
  132. ut_asserteq(-ENODEV, device_find_child_by_seq(bus, 2, true, &dev));
  133. ut_asserteq(-ENODEV, device_get_child_by_seq(bus, 2, &dev));
  134. /* Looking for something that is not a child */
  135. node = fdt_path_offset(blob, "/junk");
  136. ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
  137. node = fdt_path_offset(blob, "/d-test");
  138. ut_asserteq(-ENODEV, device_find_child_by_of_offset(bus, node, &dev));
  139. return 0;
  140. }
  141. DM_TEST(dm_test_bus_children_funcs, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  142. static int dm_test_bus_children_of_offset(struct unit_test_state *uts)
  143. {
  144. const void *blob = gd->fdt_blob;
  145. struct udevice *bus, *dev;
  146. int node;
  147. ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
  148. ut_assertnonnull(bus);
  149. /* Find a valid child */
  150. node = fdt_path_offset(blob, "/some-bus/c-test@1");
  151. ut_assert(node > 0);
  152. ut_assertok(device_find_child_by_of_offset(bus, node, &dev));
  153. ut_assertnonnull(dev);
  154. ut_assert(!(dev->flags & DM_FLAG_ACTIVATED));
  155. ut_assertok(device_get_child_by_of_offset(bus, node, &dev));
  156. ut_assertnonnull(dev);
  157. ut_assert(dev->flags & DM_FLAG_ACTIVATED);
  158. return 0;
  159. }
  160. DM_TEST(dm_test_bus_children_of_offset,
  161. DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT | DM_TESTF_FLAT_TREE);
  162. /* Test that we can iterate through children */
  163. static int dm_test_bus_children_iterators(struct unit_test_state *uts)
  164. {
  165. struct udevice *bus, *dev, *child;
  166. /* Walk through the children one by one */
  167. ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
  168. ut_assertok(device_find_first_child(bus, &dev));
  169. ut_asserteq_str("c-test@5", dev->name);
  170. ut_assertok(device_find_next_child(&dev));
  171. ut_asserteq_str("c-test@0", dev->name);
  172. ut_assertok(device_find_next_child(&dev));
  173. ut_asserteq_str("c-test@1", dev->name);
  174. ut_assertok(device_find_next_child(&dev));
  175. ut_asserteq_ptr(dev, NULL);
  176. /* Move to the next child without using device_find_first_child() */
  177. ut_assertok(device_find_child_by_seq(bus, 5, true, &dev));
  178. ut_asserteq_str("c-test@5", dev->name);
  179. ut_assertok(device_find_next_child(&dev));
  180. ut_asserteq_str("c-test@0", dev->name);
  181. /* Try a device with no children */
  182. ut_assertok(device_find_first_child(dev, &child));
  183. ut_asserteq_ptr(child, NULL);
  184. return 0;
  185. }
  186. DM_TEST(dm_test_bus_children_iterators,
  187. DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  188. /* Test that the bus can store data about each child */
  189. static int test_bus_parent_data(struct unit_test_state *uts)
  190. {
  191. struct dm_test_parent_data *parent_data;
  192. struct udevice *bus, *dev;
  193. struct uclass *uc;
  194. int value;
  195. ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
  196. /* Check that parent data is allocated */
  197. ut_assertok(device_find_child_by_seq(bus, 0, true, &dev));
  198. ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
  199. ut_assertok(device_get_child_by_seq(bus, 0, &dev));
  200. parent_data = dev_get_parent_priv(dev);
  201. ut_assert(NULL != parent_data);
  202. /* Check that it starts at 0 and goes away when device is removed */
  203. parent_data->sum += 5;
  204. ut_asserteq(5, parent_data->sum);
  205. device_remove(dev, DM_REMOVE_NORMAL);
  206. ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
  207. /* Check that we can do this twice */
  208. ut_assertok(device_get_child_by_seq(bus, 0, &dev));
  209. parent_data = dev_get_parent_priv(dev);
  210. ut_assert(NULL != parent_data);
  211. parent_data->sum += 5;
  212. ut_asserteq(5, parent_data->sum);
  213. /* Add parent data to all children */
  214. ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
  215. value = 5;
  216. uclass_foreach_dev(dev, uc) {
  217. /* Ignore these if they are not on this bus */
  218. if (dev->parent != bus) {
  219. ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
  220. continue;
  221. }
  222. ut_assertok(device_probe(dev));
  223. parent_data = dev_get_parent_priv(dev);
  224. parent_data->sum = value;
  225. value += 5;
  226. }
  227. /* Check it is still there */
  228. value = 5;
  229. uclass_foreach_dev(dev, uc) {
  230. /* Ignore these if they are not on this bus */
  231. if (dev->parent != bus)
  232. continue;
  233. parent_data = dev_get_parent_priv(dev);
  234. ut_asserteq(value, parent_data->sum);
  235. value += 5;
  236. }
  237. return 0;
  238. }
  239. /* Test that the bus can store data about each child */
  240. static int dm_test_bus_parent_data(struct unit_test_state *uts)
  241. {
  242. return test_bus_parent_data(uts);
  243. }
  244. DM_TEST(dm_test_bus_parent_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  245. /* As above but the size is controlled by the uclass */
  246. static int dm_test_bus_parent_data_uclass(struct unit_test_state *uts)
  247. {
  248. struct driver *drv;
  249. struct udevice *bus;
  250. int size;
  251. int ret;
  252. /* Set the driver size to 0 so that the uclass size is used */
  253. ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
  254. drv = (struct driver *)bus->driver;
  255. size = drv->per_child_auto_alloc_size;
  256. #ifdef CONFIG_SANDBOX
  257. os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv));
  258. os_mprotect_allow(drv, sizeof(*drv));
  259. #endif
  260. bus->uclass->uc_drv->per_child_auto_alloc_size = size;
  261. drv->per_child_auto_alloc_size = 0;
  262. ret = test_bus_parent_data(uts);
  263. if (ret)
  264. return ret;
  265. bus->uclass->uc_drv->per_child_auto_alloc_size = 0;
  266. drv->per_child_auto_alloc_size = size;
  267. return 0;
  268. }
  269. DM_TEST(dm_test_bus_parent_data_uclass,
  270. DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  271. /* Test that the bus ops are called when a child is probed/removed */
  272. static int dm_test_bus_parent_ops(struct unit_test_state *uts)
  273. {
  274. struct dm_test_parent_data *parent_data;
  275. struct dm_test_state *dms = uts->priv;
  276. struct udevice *bus, *dev;
  277. struct uclass *uc;
  278. test_state = dms;
  279. ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
  280. ut_assertok(uclass_get(UCLASS_TEST_FDT, &uc));
  281. uclass_foreach_dev(dev, uc) {
  282. /* Ignore these if they are not on this bus */
  283. if (dev->parent != bus)
  284. continue;
  285. ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
  286. ut_assertok(device_probe(dev));
  287. parent_data = dev_get_parent_priv(dev);
  288. ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
  289. }
  290. uclass_foreach_dev(dev, uc) {
  291. /* Ignore these if they are not on this bus */
  292. if (dev->parent != bus)
  293. continue;
  294. parent_data = dev_get_parent_priv(dev);
  295. ut_asserteq(FLAG_CHILD_PROBED, parent_data->flag);
  296. ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
  297. ut_asserteq_ptr(NULL, dev_get_parent_priv(dev));
  298. ut_asserteq_ptr(dms->removed, dev);
  299. }
  300. test_state = NULL;
  301. return 0;
  302. }
  303. DM_TEST(dm_test_bus_parent_ops, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  304. static int test_bus_parent_platdata(struct unit_test_state *uts)
  305. {
  306. struct dm_test_parent_platdata *plat;
  307. struct udevice *bus, *dev;
  308. /* Check that the bus has no children */
  309. ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
  310. device_find_first_child(bus, &dev);
  311. ut_asserteq_ptr(NULL, dev);
  312. ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
  313. for (device_find_first_child(bus, &dev);
  314. dev;
  315. device_find_next_child(&dev)) {
  316. /* Check that platform data is allocated */
  317. plat = dev_get_parent_platdata(dev);
  318. ut_assert(plat != NULL);
  319. /*
  320. * Check that it is not affected by the device being
  321. * probed/removed
  322. */
  323. plat->count++;
  324. ut_asserteq(1, plat->count);
  325. device_probe(dev);
  326. device_remove(dev, DM_REMOVE_NORMAL);
  327. ut_asserteq_ptr(plat, dev_get_parent_platdata(dev));
  328. ut_asserteq(1, plat->count);
  329. ut_assertok(device_probe(dev));
  330. }
  331. ut_asserteq(3, device_get_child_count(bus));
  332. /* Removing the bus should also have no effect (it is still bound) */
  333. device_remove(bus, DM_REMOVE_NORMAL);
  334. for (device_find_first_child(bus, &dev);
  335. dev;
  336. device_find_next_child(&dev)) {
  337. /* Check that platform data is allocated */
  338. plat = dev_get_parent_platdata(dev);
  339. ut_assert(plat != NULL);
  340. ut_asserteq(1, plat->count);
  341. }
  342. ut_asserteq(3, device_get_child_count(bus));
  343. /* Unbind all the children */
  344. do {
  345. device_find_first_child(bus, &dev);
  346. if (dev)
  347. device_unbind(dev);
  348. } while (dev);
  349. /* Now the child platdata should be removed and re-added */
  350. device_probe(bus);
  351. for (device_find_first_child(bus, &dev);
  352. dev;
  353. device_find_next_child(&dev)) {
  354. /* Check that platform data is allocated */
  355. plat = dev_get_parent_platdata(dev);
  356. ut_assert(plat != NULL);
  357. ut_asserteq(0, plat->count);
  358. }
  359. ut_asserteq(3, device_get_child_count(bus));
  360. return 0;
  361. }
  362. /* Test that the bus can store platform data about each child */
  363. static int dm_test_bus_parent_platdata(struct unit_test_state *uts)
  364. {
  365. return test_bus_parent_platdata(uts);
  366. }
  367. DM_TEST(dm_test_bus_parent_platdata, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  368. /* As above but the size is controlled by the uclass */
  369. static int dm_test_bus_parent_platdata_uclass(struct unit_test_state *uts)
  370. {
  371. struct udevice *bus;
  372. struct driver *drv;
  373. int size;
  374. int ret;
  375. /* Set the driver size to 0 so that the uclass size is used */
  376. ut_assertok(uclass_find_device(UCLASS_TEST_BUS, 0, &bus));
  377. drv = (struct driver *)bus->driver;
  378. size = drv->per_child_platdata_auto_alloc_size;
  379. #ifdef CONFIG_SANDBOX
  380. os_mprotect_allow(bus->uclass->uc_drv, sizeof(*bus->uclass->uc_drv));
  381. os_mprotect_allow(drv, sizeof(*drv));
  382. #endif
  383. bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = size;
  384. drv->per_child_platdata_auto_alloc_size = 0;
  385. ret = test_bus_parent_platdata(uts);
  386. if (ret)
  387. return ret;
  388. bus->uclass->uc_drv->per_child_platdata_auto_alloc_size = 0;
  389. drv->per_child_platdata_auto_alloc_size = size;
  390. return 0;
  391. }
  392. DM_TEST(dm_test_bus_parent_platdata_uclass,
  393. DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  394. /* Test that the child post_bind method is called */
  395. static int dm_test_bus_child_post_bind(struct unit_test_state *uts)
  396. {
  397. struct dm_test_parent_platdata *plat;
  398. struct udevice *bus, *dev;
  399. ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
  400. for (device_find_first_child(bus, &dev);
  401. dev;
  402. device_find_next_child(&dev)) {
  403. /* Check that platform data is allocated */
  404. plat = dev_get_parent_platdata(dev);
  405. ut_assert(plat != NULL);
  406. ut_asserteq(1, plat->bind_flag);
  407. }
  408. ut_asserteq(3, device_get_child_count(bus));
  409. return 0;
  410. }
  411. DM_TEST(dm_test_bus_child_post_bind, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  412. /* Test that the child post_bind method is called */
  413. static int dm_test_bus_child_post_bind_uclass(struct unit_test_state *uts)
  414. {
  415. struct dm_test_parent_platdata *plat;
  416. struct udevice *bus, *dev;
  417. ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
  418. for (device_find_first_child(bus, &dev);
  419. dev;
  420. device_find_next_child(&dev)) {
  421. /* Check that platform data is allocated */
  422. plat = dev_get_parent_platdata(dev);
  423. ut_assert(plat != NULL);
  424. ut_asserteq(2, plat->uclass_bind_flag);
  425. }
  426. ut_asserteq(3, device_get_child_count(bus));
  427. return 0;
  428. }
  429. DM_TEST(dm_test_bus_child_post_bind_uclass,
  430. DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  431. /*
  432. * Test that the bus' uclass' child_pre_probe() is called before the
  433. * device's probe() method
  434. */
  435. static int dm_test_bus_child_pre_probe_uclass(struct unit_test_state *uts)
  436. {
  437. struct udevice *bus, *dev;
  438. /*
  439. * See testfdt_drv_probe() which effectively checks that the uclass
  440. * flag is set before that method is called
  441. */
  442. ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
  443. for (device_find_first_child(bus, &dev);
  444. dev;
  445. device_find_next_child(&dev)) {
  446. struct dm_test_priv *priv = dev_get_priv(dev);
  447. /* Check that things happened in the right order */
  448. ut_asserteq_ptr(NULL, priv);
  449. ut_assertok(device_probe(dev));
  450. priv = dev_get_priv(dev);
  451. ut_assert(priv != NULL);
  452. ut_asserteq(1, priv->uclass_flag);
  453. ut_asserteq(1, priv->uclass_total);
  454. }
  455. ut_asserteq(3, device_get_child_count(bus));
  456. return 0;
  457. }
  458. DM_TEST(dm_test_bus_child_pre_probe_uclass,
  459. DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
  460. /*
  461. * Test that the bus' uclass' child_post_probe() is called after the
  462. * device's probe() method
  463. */
  464. static int dm_test_bus_child_post_probe_uclass(struct unit_test_state *uts)
  465. {
  466. struct udevice *bus, *dev;
  467. /*
  468. * See testfdt_drv_probe() which effectively initializes that
  469. * the uclass postp flag is set to a value
  470. */
  471. ut_assertok(uclass_get_device(UCLASS_TEST_BUS, 0, &bus));
  472. for (device_find_first_child(bus, &dev);
  473. dev;
  474. device_find_next_child(&dev)) {
  475. struct dm_test_priv *priv = dev_get_priv(dev);
  476. /* Check that things happened in the right order */
  477. ut_asserteq_ptr(NULL, priv);
  478. ut_assertok(device_probe(dev));
  479. priv = dev_get_priv(dev);
  480. ut_assert(priv != NULL);
  481. ut_asserteq(0, priv->uclass_postp);
  482. }
  483. ut_asserteq(3, device_get_child_count(bus));
  484. return 0;
  485. }
  486. DM_TEST(dm_test_bus_child_post_probe_uclass,
  487. DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);