e100_test.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:12k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*******************************************************************************
  2.   
  3.   Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
  4.   
  5.   This program is free software; you can redistribute it and/or modify it 
  6.   under the terms of the GNU General Public License as published by the Free 
  7.   Software Foundation; either version 2 of the License, or (at your option) 
  8.   any later version.
  9.   
  10.   This program is distributed in the hope that it will be useful, but WITHOUT 
  11.   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
  12.   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
  13.   more details.
  14.   
  15.   You should have received a copy of the GNU General Public License along with
  16.   this program; if not, write to the Free Software Foundation, Inc., 59 
  17.   Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.   
  19.   The full GNU General Public License is included in this distribution in the
  20.   file called LICENSE.
  21.   
  22.   Contact Information:
  23.   Linux NICS <linux.nics@intel.com>
  24.   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  25. *******************************************************************************/
  26. #include "e100.h"
  27. #include "e100_config.h"
  28. extern u16 e100_eeprom_read(struct e100_private *, u16);
  29. extern int e100_wait_exec_cmplx(struct e100_private *, u32,u8);
  30. extern void e100_phy_reset(struct e100_private *bdp);
  31. extern void e100_phy_autoneg(struct e100_private *bdp);
  32. extern void e100_phy_set_loopback(struct e100_private *bdp);
  33. extern void e100_force_speed_duplex(struct e100_private *bdp);
  34. static u8 e100_diag_selftest(struct net_device *);
  35. static u8 e100_diag_eeprom(struct net_device *);
  36. static u8 e100_diag_loopback(struct net_device *);
  37. static u8 e100_diag_one_loopback (struct net_device *, u8);
  38. static u8 e100_diag_rcv_loopback_pkt(struct e100_private *);
  39. static void e100_diag_config_loopback(struct e100_private *, u8, u8, u8 *,u8 *);
  40. static u8 e100_diag_loopback_alloc(struct e100_private *);
  41. static void e100_diag_loopback_cu_ru_exec(struct e100_private *);
  42. static u8 e100_diag_check_pkt(u8 *);
  43. static void e100_diag_loopback_free(struct e100_private *);
  44. #define LB_PACKET_SIZE 1500
  45. /**
  46.  * e100_run_diag - main test execution handler - checks mask of requests and calls the diag routines  
  47.  * @dev: atapter's net device data struct
  48.  * @test_info: array with test request mask also used to store test results
  49.  *
  50.  * RETURNS: updated flags field of struct ethtool_test
  51.  */
  52. u32
  53. e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags)
  54. {
  55. struct e100_private* bdp = dev->priv;
  56. u8 test_result = true;
  57. e100_isolate_driver(bdp);
  58. if (flags & ETH_TEST_FL_OFFLINE) {
  59. u8 fail_mask;
  60. fail_mask = e100_diag_selftest(dev);
  61. if (fail_mask) {
  62. test_result = false;
  63. if (fail_mask & REGISTER_TEST_FAIL)
  64. test_info [E100_REG_TEST_FAIL] = true;
  65. if (fail_mask & ROM_TEST_FAIL)
  66. test_info [E100_ROM_TEST_FAIL] = true;
  67. if (fail_mask & SELF_TEST_FAIL)
  68. test_info [E100_MAC_TEST_FAIL] = true;
  69. if (fail_mask & TEST_TIMEOUT)
  70. test_info [E100_CHIP_TIMEOUT] = true;
  71. }
  72. fail_mask = e100_diag_loopback(dev);
  73. if (fail_mask) {
  74. test_result = false;
  75. if (fail_mask & PHY_LOOPBACK)
  76. test_info [E100_LPBK_PHY_FAIL] = true;
  77. if (fail_mask & MAC_LOOPBACK)
  78. test_info [E100_LPBK_MAC_FAIL] = true;
  79. }
  80. }
  81. if (!e100_diag_eeprom(dev)) {
  82. test_result = false;
  83. test_info [E100_EEPROM_TEST_FAIL] = true;
  84. }
  85. /* fully recover only if the device is open*/
  86. if (netif_running(dev))  {
  87. e100_deisolate_driver(bdp, true, false);
  88. } else {
  89.      e100_deisolate_driver(bdp, false, false);
  90. }
  91. /*Let card recover from the test*/
  92. set_current_state(TASK_UNINTERRUPTIBLE);
  93. schedule_timeout(HZ * 2);
  94. return flags | (test_result ? 0 : ETH_TEST_FL_FAILED);
  95. }
  96. /**
  97.  * e100_diag_selftest - run hardware selftest 
  98.  * @dev: atapter's net device data struct
  99.  */
  100. static u8
  101. e100_diag_selftest(struct net_device *dev)
  102. {
  103. struct e100_private *bdp = dev->priv;
  104. u32 st_timeout, st_result;
  105. u8 retval = 0;
  106. if (!e100_selftest(bdp, &st_timeout, &st_result)) {
  107. if (!st_timeout) {
  108. if (st_result & CB_SELFTEST_REGISTER_BIT)
  109. retval |= REGISTER_TEST_FAIL;
  110. if (st_result & CB_SELFTEST_DIAG_BIT)
  111. retval |= SELF_TEST_FAIL;
  112. if (st_result & CB_SELFTEST_ROM_BIT)
  113. retval |= ROM_TEST_FAIL;
  114. } else {
  115.              retval = TEST_TIMEOUT;
  116. }
  117. }
  118. e100_hw_reset_recover(bdp,PORT_SOFTWARE_RESET);
  119. return retval;
  120. }
  121. /**
  122.  * e100_diag_eeprom - validate eeprom checksum correctness
  123.  * @dev: atapter's net device data struct
  124.  *
  125.  */
  126. static u8
  127. e100_diag_eeprom (struct net_device *dev)
  128. {
  129. struct e100_private *bdp = dev->priv;
  130. u16 i, eeprom_sum, eeprom_actual_csm;
  131. for (i = 0, eeprom_sum = 0; i < (bdp->eeprom_size - 1); i++) {
  132. eeprom_sum += e100_eeprom_read(bdp, i);
  133. }
  134. eeprom_actual_csm = e100_eeprom_read(bdp, bdp->eeprom_size - 1);
  135. if (eeprom_actual_csm == (u16)(EEPROM_SUM - eeprom_sum)) {
  136. return true;
  137. }
  138. return false;
  139. }
  140. /**
  141.  * e100_diag_loopback - performs loopback test  
  142.  * @dev: atapter's net device data struct
  143.  */
  144. static u8
  145. e100_diag_loopback (struct net_device *dev)
  146. {
  147. u8 rc = 0;
  148. if (!e100_diag_one_loopback(dev, PHY_LOOPBACK)) {
  149. rc |= PHY_LOOPBACK;
  150. }
  151. if (!e100_diag_one_loopback(dev, MAC_LOOPBACK)) {
  152. rc |= MAC_LOOPBACK;
  153. }
  154. return rc;
  155. }
  156. /**
  157.  * e100_diag_loopback - performs loopback test  
  158.  * @dev: atapter's net device data struct
  159.  * @mode: lopback test type
  160.  */
  161. static u8
  162. e100_diag_one_loopback (struct net_device *dev, u8 mode)
  163. {
  164.         struct e100_private *bdp = dev->priv;
  165.         u8 res = false;
  166.     u8 saved_dynamic_tbd = false;
  167.     u8 saved_extended_tcb = false;
  168. if (!e100_diag_loopback_alloc(bdp))
  169. return false;
  170. /* change the config block to standard tcb and the correct loopback */
  171.         e100_diag_config_loopback(bdp, true, mode,
  172.   &saved_extended_tcb, &saved_dynamic_tbd);
  173. e100_diag_loopback_cu_ru_exec(bdp);
  174.         if (e100_diag_rcv_loopback_pkt(bdp)) {
  175. res = true;
  176. }
  177.         e100_diag_loopback_free(bdp);
  178.         /* change the config block to previous tcb mode and the no loopback */
  179.         e100_diag_config_loopback(bdp, false, mode,
  180.   &saved_extended_tcb, &saved_dynamic_tbd);
  181. return res;
  182. }
  183. /**
  184.  * e100_diag_config_loopback - setup/clear loopback before/after lpbk test
  185.  * @bdp: atapter's private data struct
  186.  * @set_loopback: true if the function is called to set lb
  187.  * @loopback_mode: the loopback mode(MAC or PHY)
  188.  * @tcb_extended: true if need to set extended tcb mode after clean loopback
  189.  * @dynamic_tbd: true if needed to set dynamic tbd mode after clean loopback
  190.  *
  191.  */
  192. void
  193. e100_diag_config_loopback(struct e100_private* bdp,
  194.   u8 set_loopback,
  195.   u8 loopback_mode,
  196.   u8* tcb_extended,
  197.   u8* dynamic_tbd)
  198. {
  199. /* if set_loopback == true - we want to clear tcb_extended/dynamic_tbd.
  200.  * the previous values are saved in the params tcb_extended/dynamic_tbd
  201.  * if set_loopback == false - we want to restore previous value.
  202.  */
  203. if (set_loopback || (*tcb_extended))
  204.   *tcb_extended = e100_config_tcb_ext_enable(bdp,*tcb_extended);
  205. if (set_loopback || (*dynamic_tbd))
  206.  *dynamic_tbd = e100_config_dynamic_tbd(bdp,*dynamic_tbd);
  207. if (set_loopback) {
  208. /* Configure loopback on MAC */
  209. e100_config_loopback_mode(bdp,loopback_mode);
  210. } else {
  211. e100_config_loopback_mode(bdp,NO_LOOPBACK);
  212. }
  213. e100_config(bdp);
  214. if (loopback_mode == PHY_LOOPBACK) {
  215. if (set_loopback)
  216.                         /* Set PHY loopback mode */
  217.                         e100_phy_set_loopback(bdp);
  218.                 else { /* Back to normal speed and duplex */
  219.                  if (bdp->params.e100_speed_duplex == E100_AUTONEG)
  220. /* Reset PHY and do autoneg */
  221.                          e100_phy_autoneg(bdp);
  222. else    
  223. /* Reset PHY and force speed and duplex */
  224. e100_force_speed_duplex(bdp);
  225. }
  226.                 /* Wait for PHY state change */
  227. set_current_state(TASK_UNINTERRUPTIBLE);
  228.                 schedule_timeout(HZ);
  229. } else { /* For MAC loopback wait 500 msec to take effect */
  230. set_current_state(TASK_UNINTERRUPTIBLE);
  231. schedule_timeout(HZ / 2);
  232. }
  233. }
  234.   
  235. /**
  236.  * e100_diag_loopback_alloc - alloc & initate tcb and rfd for the loopback
  237.  * @bdp: atapter's private data struct
  238.  *
  239.  */
  240. static u8
  241. e100_diag_loopback_alloc(struct e100_private *bdp)
  242. {
  243. dma_addr_t dma_handle;
  244. tcb_t *tcb;
  245. rfd_t *rfd;
  246. tbd_t *tbd;
  247. /* tcb, tbd and transmit buffer are allocated */
  248. tcb = pci_alloc_consistent(bdp->pdev,
  249.    (sizeof (tcb_t) + sizeof (tbd_t) +
  250.     LB_PACKET_SIZE),
  251.    &dma_handle);
  252.         if (tcb == NULL)
  253. return false;
  254. memset(tcb, 0x00, sizeof (tcb_t) + sizeof (tbd_t) + LB_PACKET_SIZE);
  255. tcb->tcb_phys = dma_handle;
  256. tcb->tcb_hdr.cb_status = 0;
  257. tcb->tcb_hdr.cb_cmd =
  258. cpu_to_le16(CB_EL_BIT | CB_TRANSMIT | CB_TX_SF_BIT);
  259. /* Next command is null */
  260. tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(0xffffffff);
  261. tcb->tcb_cnt = 0;
  262. tcb->tcb_thrshld = bdp->tx_thld;
  263. tcb->tcb_tbd_num = 1;
  264. /* Set up tcb tbd pointer */
  265. tcb->tcb_tbd_ptr = cpu_to_le32(tcb->tcb_phys + sizeof (tcb_t));
  266. tbd = (tbd_t *) ((u8 *) tcb + sizeof (tcb_t));
  267. /* Set up tbd transmit buffer */
  268. tbd->tbd_buf_addr =
  269. cpu_to_le32(le32_to_cpu(tcb->tcb_tbd_ptr) + sizeof (tbd_t));
  270. tbd->tbd_buf_cnt = __constant_cpu_to_le16(1024);
  271. /* The value of first 512 bytes is FF */
  272. memset((void *) ((u8 *) tbd + sizeof (tbd_t)), 0xFF, 512);
  273. /* The value of second 512 bytes is BA */
  274. memset((void *) ((u8 *) tbd + sizeof (tbd_t) + 512), 0xBA, 512);
  275. wmb();
  276. rfd = pci_alloc_consistent(bdp->pdev, sizeof (rfd_t), &dma_handle);
  277. if (rfd == NULL) {
  278. pci_free_consistent(bdp->pdev,
  279.     sizeof (tcb_t) + sizeof (tbd_t) +
  280.     LB_PACKET_SIZE, tcb, tcb->tcb_phys);
  281. return false;
  282. }
  283. memset(rfd, 0x00, sizeof (rfd_t));
  284. /* init all fields in rfd */
  285. rfd->rfd_header.cb_cmd = cpu_to_le16(RFD_EL_BIT);
  286. rfd->rfd_sz = cpu_to_le16(ETH_FRAME_LEN + CHKSUM_SIZE);
  287. /* dma_handle is physical address of rfd */
  288. bdp->loopback.dma_handle = dma_handle;
  289. bdp->loopback.tcb = tcb;
  290. bdp->loopback.rfd = rfd;
  291. wmb();
  292. return true;
  293. }
  294. /**
  295.  * e100_diag_loopback_cu_ru_exec - activates cu and ru to send & receive the pkt
  296.  * @bdp: atapter's private data struct
  297.  *
  298.  */
  299. static void
  300. e100_diag_loopback_cu_ru_exec(struct e100_private *bdp)
  301. {
  302. /*load CU & RU base */ 
  303. if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE))
  304. printk("e100: SCB_CUC_LOAD_BASE failedn");
  305. if(!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE))
  306. printk("e100: SCB_RUC_LOAD_BASE failed!n");
  307. if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START))
  308. printk("e100: SCB_RUC_START failed!n");
  309. bdp->next_cu_cmd = START_WAIT;
  310. e100_start_cu(bdp, bdp->loopback.tcb);
  311. bdp->last_tcb = NULL;
  312. rmb();
  313. }
  314. /**
  315.  * e100_diag_check_pkt - checks if a given packet is a loopback packet
  316.  * @bdp: atapter's private data struct
  317.  *
  318.  * Returns true if OK false otherwise.
  319.  */
  320. static u8
  321. e100_diag_check_pkt(u8 *datap)
  322. {
  323. int i;
  324. for (i = 0; i<512; i++) {
  325. if( !((*datap)==0xFF && (*(datap + 512) == 0xBA)) ) {
  326. printk (KERN_ERR "e100: check loopback packet failed at: %xn", i);
  327. return false;
  328. }
  329. }
  330. printk (KERN_DEBUG "e100: Check received loopback packet OKn");
  331. return true;
  332. }
  333. /**
  334.  * e100_diag_rcv_loopback_pkt - waits for receive and checks lpbk packet
  335.  * @bdp: atapter's private data struct
  336.  *
  337.  * Returns true if OK false otherwise.
  338.  */
  339. static u8
  340. e100_diag_rcv_loopback_pkt(struct e100_private* bdp) 
  341. {    
  342. rfd_t *rfdp;
  343. u16 rfd_status;
  344. unsigned long expires = jiffies + HZ * 2;
  345.         rfdp =bdp->loopback.rfd;
  346.         rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status);
  347.         while (!(rfd_status & RFD_STATUS_COMPLETE)) { 
  348. if (time_before(jiffies, expires)) {
  349. yield();
  350. rmb();
  351. rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status);
  352. } else {
  353. break;
  354. }
  355.         }
  356.         if (rfd_status & RFD_STATUS_COMPLETE) {
  357. printk(KERN_DEBUG "e100: Loopback packet receivedn");
  358.                 return e100_diag_check_pkt(((u8 *)rfdp+bdp->rfd_size));
  359. }
  360. else {
  361. printk(KERN_ERR "e100: Loopback packet not receivedn");
  362. return false;
  363. }
  364. }
  365. /**
  366.  * e100_diag_loopback_free - free data allocated for loopback pkt send/receive
  367.  * @bdp: atapter's private data struct
  368.  *
  369.  */
  370. static void
  371. e100_diag_loopback_free (struct e100_private *bdp)
  372. {
  373.         pci_free_consistent(bdp->pdev,
  374.     sizeof(tcb_t) + sizeof(tbd_t) + LB_PACKET_SIZE,
  375.     bdp->loopback.tcb, bdp->loopback.tcb->tcb_phys);
  376.         pci_free_consistent(bdp->pdev, sizeof(rfd_t), bdp->loopback.rfd,
  377.     bdp->loopback.dma_handle);
  378. }