Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

822 lines
23 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. sonictst.c
  5. Abstract:
  6. This module implements the SONIC ethernet test for the selftest.
  7. The test consist in transmiting packets in loopback mode.
  8. Author:
  9. Lluis Abello (lluis) 19-Feb-1991
  10. Environment:
  11. Revision History:
  12. --*/
  13. #include "fwp.h"
  14. #include "sonictst.h"
  15. #include "iodevice.h"
  16. #include "ioaccess.h"
  17. #include "fwstring.h"
  18. #ifdef DUO
  19. #include "duoint.h"
  20. #endif
  21. extern volatile ULONG TimerTicks;
  22. extern UCHAR * TranslationTable;
  23. VOID
  24. MapDma(
  25. ULONG VirtualAddress,
  26. ULONG LogicalAddress,
  27. ULONG Pages
  28. )
  29. /*++
  30. Routine description:
  31. This routine performs the I/O address maping by setting the
  32. translation table.
  33. Physical and Logical Addresses must be page aligned.
  34. Arguments:
  35. VirtualAddress - Specifies the R4000 VirtualAddress.
  36. Logical Address will be mapped to the physical
  37. address that this Virtual Address Maps.
  38. LogicalAdress - Address to map
  39. Pages - Number of pages to map
  40. Return value:
  41. None.
  42. --*/
  43. {
  44. PTRANSLATION_ENTRY TranslationTable;
  45. ULONG PageFrameNumber,LogicalPage,PhysicalAddress;
  46. ULONG i;
  47. PhysicalAddress=VirtualAddress&0x0FFFFFFF; // Extract Physical Address from KSEG0-1
  48. TranslationTable= (PTRANSLATION_ENTRY)((READ_REGISTER_ULONG(&DMA_CONTROL->TranslationBase.Long)) | 0xA0000000);
  49. // Initialize pointer to base
  50. // of Table to write the new entries.
  51. // Make physical address virtual
  52. // Non cached because we want it
  53. // to be written to memory
  54. LogicalPage= LogicalAddress>>12;
  55. PageFrameNumber=PhysicalAddress&0x03FFF000;
  56. for (i=0;i < Pages;i++) {
  57. TranslationTable[LogicalPage+i].PageFrame=PageFrameNumber;
  58. PageFrameNumber+=0x1000; // next page starts after 4Kb more
  59. TranslationTable[LogicalPage+i].Fill=0;
  60. }
  61. WRITE_REGISTER_ULONG(&DMA_CONTROL->TranslationLimit.Long,(LogicalPage+i) << 3);
  62. }
  63. VOID
  64. AllocateReceiveDescriptors(
  65. )
  66. /*++
  67. Routine Description:
  68. This routine allocates and initializes a chain of 3 Receive Descriptors.
  69. The Receive Descriptors are linked in a circular queue so that the
  70. pointers don't need to be changed any more. The last Receive descriptor
  71. points to the first but it has the EOL flag set so it's the last on the
  72. queue and therefore sonic will not use the following descriptor (first one)
  73. until we free it. Once we process a received packet, the EOL flag must be
  74. rotated to the next descriptor to make a new descriptor available.
  75. In order to be able to use the link field from both physical (system soft)
  76. and logical (sonic) address spaces the receive descriptors must have
  77. the same alignment for both physical and logical addresses.
  78. Arguments:
  79. None.
  80. Return Value:
  81. None.
  82. --*/
  83. {
  84. ULONG Link,i;
  85. ULONG LogicalReceiveDscr;
  86. ReceiveDscrQueue.Base = (PRECEIVE_DESCRIPTOR) PHYS_RECEIVE_DSCR_ADDRESS;
  87. LogicalReceiveDscr = LOGICAL_RECEIVE_DSCR_ADDRESS;
  88. MapDma((ULONG)ReceiveDscrQueue.Base, // R4000 Address
  89. LogicalReceiveDscr, // Logical Address
  90. 1 // 1 page
  91. );
  92. //get 16 lower bits of address or offset
  93. ReceiveDscrQueue.Current=Link=(ULONG)ReceiveDscrQueue.Base & 0xFFFF;
  94. //
  95. // Link first descriptor to the second one.
  96. //
  97. for (i=0;i<2;i++) {
  98. Link += sizeof(RECEIVE_DESCRIPTOR);
  99. (ReceiveDscrQueue.Base[i]).Link.Data=Link; // Link to next RD
  100. (ReceiveDscrQueue.Base[i]).InUse.Data=AVAILABLE; // Make it avilable
  101. }
  102. //
  103. // Link last descriptor to the first but mark it as EOL
  104. //
  105. (ReceiveDscrQueue.Base[2]).Link.Data=ReceiveDscrQueue.Current | EOL;
  106. //
  107. // Make it avilable
  108. //
  109. (ReceiveDscrQueue.Base[2]).InUse.Data=AVAILABLE;
  110. ReceiveDscrQueue.Last=Link; // Keep track of the last one.
  111. // we need only the upper bits to access a descriptor as Base | First
  112. ReceiveDscrQueue.Base = (PRECEIVE_DESCRIPTOR)((ULONG) ReceiveDscrQueue.Base & 0xFFFF0000);
  113. //
  114. // Initialize sonic Receive descriptor pointers with the logical address
  115. // of the descriptors.
  116. //
  117. WRITE_REGISTER_USHORT(&SONIC->URDA.Reg,(USHORT) (LogicalReceiveDscr >> 16));
  118. WRITE_REGISTER_USHORT(&SONIC->CRDA.Reg,ReceiveDscrQueue.Current);
  119. }
  120. VOID
  121. AllocateReceiveResources(
  122. )
  123. /*++
  124. Routine Description:
  125. This routine allocates and initializes the Receive Resource area.
  126. Two resources are allocated.
  127. The pointer of each entry points to the Receive Buffers which are
  128. also allocated by this routine. And the size of each buffer is also
  129. set in the Recieve Resource word count entry.
  130. Receive Buffers allocated are RBA_SIZE bytes long.
  131. It also allocate room for the CAM descriptors. The CAM descriptor pointer
  132. is pointed by CamDescriptor and resides inside the URRA segment.
  133. The mapping Logical <-> Physical spaces is also done.
  134. Arguments:
  135. None.
  136. Return Value:
  137. None.
  138. --*/
  139. {
  140. ULONG i;
  141. ULONG ReceivePhysBuffer; // Temporay pointer to a receive buffer area.
  142. ULONG ReceiveLogBuffer; // Temporary pointer to a logical address.
  143. //
  144. //Allocate memory for the receive descriptors + CAM Addresses + CAM enable.
  145. //
  146. ReceivePhysRsrc = (PRECEIVE_RESOURCE) RECEIVE_PHYS_RSRC_ADDRESS;
  147. ReceiveLogRsrc = (PRECEIVE_RESOURCE) RECEIVE_LOG_RSRC_ADDRESS;
  148. MapDma((ULONG)ReceivePhysRsrc,
  149. (ULONG)ReceiveLogRsrc,
  150. 1
  151. );
  152. //
  153. // Allocate Receive buffers in physical and logical spaces and map them.
  154. //
  155. ReceivePhysBuffer= (ULONG) RECEIVE_PHYS_BUFFER_ADDRESS;
  156. ReceiveLogBuffer= (ULONG) RECEIVE_LOG_BUFFER_ADDRESS;
  157. MapDma(ReceivePhysBuffer,ReceiveLogBuffer,2);
  158. //
  159. // The Receive Buffers are contiguos in memory. Sonic will write
  160. // the logical address of the packets received. To translate this
  161. // logical address to a physical one what we do is to keep the
  162. // offset between these physical and logical addresses and then
  163. // we just need to add this offset to the logical address to
  164. // convert it to physical.
  165. //
  166. ReceiveBufferTranslationOffset =ReceivePhysBuffer-ReceiveLogBuffer;
  167. //
  168. // for each receive resource, Write the logical
  169. // address of the receive buffer in the physical Receive resource.
  170. //
  171. for (i=0; i < 3; i++) {
  172. ReceivePhysRsrc[i].BufferPtr0.Data=ReceiveLogBuffer & 0xFFFF; //16 lower bits
  173. ReceivePhysRsrc[i].BufferPtr1.Data=ReceiveLogBuffer >> 16; //16 upper bits
  174. ReceivePhysRsrc[i].WordCount0.Data=((RBA_SIZE >>1) & 0xFFFF); //16 lower bits
  175. ReceivePhysRsrc[i].WordCount1.Data=(RBA_SIZE >> 17); //16 upper bits
  176. ReceiveLogBuffer += RBA_SIZE;
  177. }
  178. //
  179. // Initialize the CamDescriptor to point to the end of the RRA
  180. //
  181. PhysCamDescriptor=(PCAM_DESCRIPTOR)(&ReceivePhysRsrc[3]);
  182. LogCamDescriptor=(PCAM_DESCRIPTOR)(&ReceiveLogRsrc[3]);
  183. //
  184. // Initialize sonic Resource Area pointers with the logical address mapped
  185. // to the physical Area.
  186. //
  187. WRITE_REGISTER_USHORT(&SONIC->URRA.Reg,(USHORT) ((ULONG)ReceiveLogRsrc >> 16));
  188. WRITE_REGISTER_USHORT(&SONIC->RSA.Reg,(ULONG)ReceiveLogRsrc & 0xFFFF);
  189. WRITE_REGISTER_USHORT(&SONIC->REA.Reg,(ULONG)(&ReceiveLogRsrc[3]) & 0xFFFF);
  190. WRITE_REGISTER_USHORT(&SONIC->RRP.Reg,(ULONG)ReceiveLogRsrc & 0xFFFF);
  191. WRITE_REGISTER_USHORT(&SONIC->RWP.Reg,(ULONG)(&ReceiveLogRsrc[2]) & 0xFFFF);
  192. //
  193. // Set the lower boundary of the RBA to the maximum packet size.
  194. //
  195. WRITE_REGISTER_USHORT(&SONIC->EOBC.Reg,MAX_PACKET_SIZE >> 1);
  196. //
  197. // Set The receive control register.
  198. //
  199. WRITE_REGISTER_USHORT(&SONIC->ReceiveControl.Reg,RCR_ENDEC | RCR_RNT);
  200. }
  201. VOID
  202. SetCamDescriptor(
  203. )
  204. /*++
  205. Routine Description:
  206. This routine Initializes the CAM descriptor area allocated by
  207. "AllocateReceiveResources" and being pointed by PhysCamDescriptor.
  208. The Address loaded in the CAM is the one fetched from the NVRAM.
  209. It leaves everything ready to issue the Load CAM command.
  210. Arguments:
  211. None.
  212. Return Value:
  213. None.
  214. --*/
  215. {
  216. ULONG i;
  217. //
  218. // Initialize CAM descriptor area.
  219. //
  220. PhysCamDescriptor[0].EntryPointer.Data=0;
  221. PhysCamDescriptor[0].Port0.Data=(StationAddress[1] << 8) |
  222. (StationAddress[0]);
  223. PhysCamDescriptor[0].Port1.Data=(StationAddress[3] << 8) |
  224. (StationAddress[2]);
  225. PhysCamDescriptor[0].Port2.Data=(StationAddress[5] << 8) |
  226. (StationAddress[4]);
  227. // Set CAM Enable.
  228. PhysCamDescriptor[1].EntryPointer.Data=1; // enable entry zero.
  229. WRITE_REGISTER_USHORT(&SONIC->CamDscrCount.Reg,1); // only one entry.
  230. // Lower 16 bits offset from URRA
  231. WRITE_REGISTER_USHORT(&SONIC->CamDscrPtr.Reg,(ULONG)LogCamDescriptor & 0xFFFF);
  232. }
  233. VOID
  234. AllocateTransmitDescriptors(
  235. )
  236. /*++
  237. Routine Description:
  238. This routine allocates and initializes a pool of Transmit Descriptors.
  239. The Transmit Descriptors are set to be used one for each packet as they
  240. have only room for one fragment.
  241. The Descriptor fragment pointers are initialized to point to the
  242. Transmit Buffer Area which is also allocated.
  243. There is enough room allocated for each buffer for the bigest
  244. ethernet packet.
  245. To keep the physical addresses of the TBA we use the upper 16 bits
  246. of the SONIC_ENTRY this is the field called 'Fill'.
  247. This way we don't ahve any restriction in these pointers but we
  248. have to deal with both, physical and logical.
  249. Arguments:
  250. None.
  251. Return Value:
  252. None.
  253. --*/
  254. {
  255. ULONG i;
  256. ULONG PhysTbaPtr,LogTbaPtr; // Transmit Buffer Area pointers
  257. //
  258. // Allocate memory for transmit descriptors and map it
  259. //
  260. PhysTransmitDscr = (PTRANSMIT_DESCRIPTOR) PHYS_TRANSMIT_DSCR_ADDRESS;
  261. LogicalTransmitDscr = (PTRANSMIT_DESCRIPTOR) LOGICAL_TRANSMIT_DSCR_ADDRESS;
  262. MapDma((ULONG) PhysTransmitDscr,
  263. (ULONG) LogicalTransmitDscr,
  264. 1
  265. );
  266. //
  267. // Allocate memory for Transmit Buffer are and map it.
  268. //
  269. PhysTbaPtr = PHYS_TBA_ADDRESS;
  270. LogTbaPtr = LOG_TBA_ADDRESS;
  271. MapDma(PhysTbaPtr,LogTbaPtr,1);
  272. // Initialize fragment count to 1 (packets won't be scatered)
  273. PhysTransmitDscr->FragCount.Data = 1;
  274. //
  275. // Initialize Logical pointers to TBA
  276. //
  277. PhysTransmitDscr->FragPtr0.Data = LogTbaPtr & 0xFFFF;// lower 16 bits
  278. PhysTransmitDscr->FragPtr1.Data = LogTbaPtr >> 16; // upper 16 bits
  279. //
  280. // Initialize Physical pointer to TBA
  281. //
  282. PhysTransmitDscr->FragPtr0.Fill = PhysTbaPtr & 0xFFFF;// lower 16 bits
  283. PhysTransmitDscr->FragPtr1.Fill = PhysTbaPtr >> 16; // upper 16 bits
  284. //
  285. // Unlink the packets, we will transmit one at a time.
  286. //
  287. PhysTransmitDscr->Link.Data = EOL;
  288. PhysTransmitDscr->Config.Data = TCR_POWC;
  289. //
  290. // Initialize UTDA register. This can be done here because the base address
  291. // of the Transmit Descriptor Area will not change.
  292. // CTDA must be set after a new packet is ready to be sent.
  293. //
  294. WRITE_REGISTER_USHORT(&SONIC->UTDA.Reg,(USHORT)((ULONG)LogicalTransmitDscr>>16));
  295. }
  296. VOID
  297. ComposeMessage(
  298. ULONG Size,
  299. UCHAR FirstValue
  300. )
  301. /*++
  302. Routine Description:
  303. This routine composes a message of the specified size.
  304. It places the message in the buffer especified by the Transmit
  305. Descriptor, and initializes the descriptor.
  306. Arguments:
  307. Size - Size of the message in bytes, must be <= MAX_PACKET_SIZE
  308. FirstValue - value of first Data byte in the packet.
  309. Return Value:
  310. None.
  311. --*/
  312. {
  313. register ULONG i,j=0;
  314. PUCHAR MsgPtr; // Temporary pointer to the message area.
  315. //
  316. // Load pointer to packet
  317. //
  318. MsgPtr= (PUCHAR) ((PhysTransmitDscr->FragPtr1.Fill << 16) | (PhysTransmitDscr->FragPtr0.Fill));
  319. for (i=0; i<6; i++) {
  320. MsgPtr[j]=StationAddress[i]; // copy Destination address to packet
  321. MsgPtr[j+6]=StationAddress[i]; // copy Source address to packet
  322. j++;
  323. }
  324. j+=6;
  325. //
  326. // Set size of message
  327. //
  328. MsgPtr[j++] = Size >> 8; // upper 8 bits
  329. MsgPtr[j++] = Size & 0xFF; // lower 8 bits
  330. //
  331. // Compose message
  332. //
  333. for (i=0; i < Size; i++) {
  334. MsgPtr[j++] = FirstValue++;
  335. }
  336. //
  337. // Initialize other Transmit descriptor fields.
  338. //
  339. PhysTransmitDscr->PktSize.Data = Size+6+6+2;
  340. PhysTransmitDscr->FragSize.Data = Size+6+6+2;
  341. //
  342. // Initialize TDA registers with logical address.
  343. //
  344. WRITE_REGISTER_USHORT(&SONIC->CTDA.Reg,((ULONG) LogicalTransmitDscr) & 0xFFFF);
  345. }
  346. VOID
  347. SonicCheckError(
  348. )
  349. /*++
  350. Routine Description:
  351. This routine checks and reports error conditions after an interrupt.
  352. Arguments:
  353. None.
  354. Return Value:
  355. None.
  356. --*/
  357. {
  358. ULONG ErrorValue;
  359. SonicErrors++;
  360. if (SonicStatus.InterruptID & INT_BR) { // Bus Retry.
  361. ErrorValue= READ_REGISTER_ULONG(&DMA_CONTROL->Errortype.Long);
  362. //
  363. // Clear error by writing back the contents of the register.
  364. //
  365. WRITE_REGISTER_ULONG(&DMA_CONTROL->Errortype.Long,ErrorValue);
  366. //
  367. // Read error registers to clear them
  368. //
  369. ErrorValue= READ_REGISTER_ULONG(&DMA_CONTROL->MemoryFailedAddress.Long);
  370. ErrorValue= READ_REGISTER_ULONG(&DMA_CONTROL->RemoteFailedAddress.Long);
  371. #ifndef DUO
  372. ErrorValue= READ_REGISTER_ULONG(&DMA_CONTROL->ParityDiagnosticLow.Long);
  373. #else
  374. ErrorValue= READ_REGISTER_ULONG(&DMA_CONTROL->EccDiagnostic);
  375. #endif
  376. }
  377. }
  378. BOOLEAN
  379. WaitForSonicInterrupt(
  380. )
  381. /*++
  382. Routine Description:
  383. This routine waits for a sonic interrupt by polling the Semaphore
  384. It sets the TimerTicks variable to 20 and if it becomes zero
  385. (at least 20 millisecond has passed) it time-out.
  386. Arguments:
  387. None
  388. Return Value:
  389. FALSE if the interrupt ocurred.
  390. TRUE otherwise.
  391. --*/
  392. {
  393. ULONG i;
  394. TimerTicks=20;
  395. while (TimerTicks) { // check for timeout
  396. if (SonicIntSemaphore==0) { // if interrupt has ocurred
  397. return FALSE; // return to process
  398. }
  399. }
  400. return TRUE; // return if timeout.
  401. }
  402. VOID
  403. InitSonic(
  404. )
  405. /*++
  406. Routine Description:
  407. This routine initializes the SONIC chip.
  408. Arguments:
  409. None
  410. Return Value:
  411. None
  412. --*/
  413. {
  414. #ifdef DUO
  415. //
  416. // Enable sonic interrupts in altera
  417. //
  418. USHORT InterruptMask;
  419. InterruptMask = READ_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable);
  420. WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable,InterruptMask | (1 << 3));
  421. #endif
  422. //
  423. // Software Reset
  424. //
  425. WRITE_REGISTER_USHORT(&SONIC->Command.Reg,CR_RST);
  426. // Set Hardware dependent configuration.
  427. WRITE_REGISTER_USHORT(&SONIC->DataConfiguration.Reg,DATA_CONFIGURATION);
  428. // Clear Reset
  429. WRITE_REGISTER_USHORT(&SONIC->Command.Reg,0);
  430. //
  431. // Initialize all these messy tables of descriptors...
  432. //
  433. AllocateReceiveDescriptors();
  434. AllocateReceiveResources();
  435. SetCamDescriptor();
  436. AllocateTransmitDescriptors();
  437. //
  438. // Set Interrupt Mask
  439. //
  440. WRITE_REGISTER_USHORT(&SONIC->InterruptMask.Reg,( INT_BR |
  441. INT_LCD |
  442. INT_PKTRX |
  443. INT_TXDN |
  444. INT_TXER |
  445. INT_RDE |
  446. INT_RBE |
  447. INT_RBAE |
  448. INT_RFO));
  449. //
  450. //Issue Load CAM Command and wait for this interrupt.
  451. //
  452. SonicStatus.ExpectedInt = INT_LCD; // Expect an INT_LCD interrupt.
  453. SonicIntSemaphore=1;
  454. WRITE_REGISTER_USHORT(&SONIC->Command.Reg,CR_LCAM);
  455. if (WaitForSonicInterrupt()) {
  456. FwPrint("Timeout waiting for sonic int\r\n");
  457. SonicErrors++;
  458. return;
  459. }
  460. if (SonicStatus.Status==DONE) {
  461. SonicStatus.ExpectedInt=0; // clear expected interrupts.
  462. } else {
  463. FwPrint("Sonic status not DONE\r\n");
  464. SonicErrors++;
  465. }
  466. //
  467. // Issue the RRA Read Command
  468. //
  469. WRITE_REGISTER_USHORT(&SONIC->Command.Reg,CR_RRA);
  470. while (READ_REGISTER_USHORT(&SONIC->Command.Reg) & CR_RRA) { // Wait until the command is processed.
  471. }
  472. //
  473. // Enable Reception.
  474. //
  475. WRITE_REGISTER_USHORT(&SONIC->Command.Reg,CR_RXEN);
  476. while (READ_REGISTER_USHORT(&SONIC->Command.Reg) & CR_RXDIS) { // wait until reception is enabled.
  477. }
  478. }
  479. VOID
  480. SonicInterrupt(
  481. )
  482. /*++
  483. Routine Description:
  484. This routine is the SONIC port service interrupt. It will be called from
  485. the Trap Handler when getting an interrupt from the SONIC.
  486. Arguments:
  487. None.
  488. Return Value:
  489. None.
  490. --*/
  491. {
  492. register USHORT InterruptStatus,NotCleared;
  493. //
  494. // Read Interrupt Status register
  495. //
  496. InterruptStatus= READ_REGISTER_USHORT(&SONIC->InterruptStatus.Reg);
  497. //
  498. // clear interrupt writing it back
  499. //
  500. WRITE_REGISTER_USHORT(&SONIC->InterruptStatus.Reg,InterruptStatus);
  501. InterruptStatus= InterruptStatus & (~INT_HBL); // clear HBL bit.
  502. if (EXPECTED_INT && NO_OTHER_INT) {
  503. if (InterruptStatus & INT_TXDN) {
  504. //
  505. // Packet Transmited
  506. //
  507. SonicStatus.ExpectedInt &= ~INT_TXDN; // clear expected bit.
  508. // check if it was properly sent.
  509. SonicStatus.TransmitControl=READ_REGISTER_USHORT(&SONIC->TransmitControl.Reg);
  510. if (SonicStatus.TransmitControl & (TCR_BCM | TCR_EXC | TCR_FU | TCR_EXD)) {
  511. //Error Transmiting
  512. SonicStatus.Status=ERROR;
  513. SonicStatus.InterruptID = InterruptStatus;
  514. SonicIntSemaphore = 0; // signal that the interrupt occurred.
  515. return;
  516. }
  517. }
  518. if (InterruptStatus & INT_PKTRX) { // packet received
  519. SonicStatus.ExpectedInt &= ~INT_PKTRX; // clear interrupt
  520. }
  521. if (InterruptStatus & INT_LCD) { // load cam interrupt
  522. SonicStatus.ExpectedInt &= ~INT_LCD; // clear interrupt
  523. }
  524. if (SonicStatus.ExpectedInt) { // we still want another interrupt
  525. return;
  526. } else {
  527. SonicStatus.Status=DONE;
  528. SonicIntSemaphore = 0; // signal that the interrupt occurred.
  529. return;
  530. }
  531. } else { // we got an interrupt not expected.
  532. SonicStatus.InterruptID=InterruptStatus;
  533. SonicStatus.TransmitControl=READ_REGISTER_USHORT(&SONIC->TransmitControl.Reg);
  534. SonicStatus.Status=ERROR;
  535. SonicIntSemaphore = 0; // signal that the interrupt ocurred.
  536. return;
  537. }
  538. }
  539. ULONG
  540. SonicCheckReception(
  541. )
  542. /*++
  543. Routine Description:
  544. This routine compares the sent packet with the received one.
  545. Makes the used Receive Descriptor available, and if the Receive Buffer
  546. is full it makes the used receive resurce available.
  547. Arguments:
  548. None.
  549. Return Value:
  550. ERROR - If errors are found
  551. DONE - If no errors
  552. --*/
  553. {
  554. PUCHAR SentMsg,ReceivedMsg;
  555. USHORT ReceiveStatus,TransmitControl;
  556. ULONG PktSize,i;
  557. if(CURRENT_DESCRIPTOR->InUse.Data) {
  558. FwPrint("Descriptor in use\r\n");
  559. SonicErrors++;
  560. return ERROR;
  561. }
  562. ReceiveStatus=CURRENT_DESCRIPTOR->Status.Data;
  563. if (ReceiveStatus & (RCR_MC | RCR_BC | RCR_COL | RCR_CRCR | RCR_FAER)) {
  564. FwPrint("Receive status %lx \r\n",ReceiveStatus);
  565. SonicErrors++;
  566. return ERROR;
  567. }
  568. //
  569. // Get ptr to packet and add the offset between Logical and Physical
  570. // to obtain the physical ptr.
  571. //
  572. ReceivedMsg=(PUCHAR) (( (CURRENT_DESCRIPTOR->PktPtr1.Data << 16) |
  573. (CURRENT_DESCRIPTOR->PktPtr0.Data))
  574. + ReceiveBufferTranslationOffset);
  575. SentMsg=(PUCHAR) (
  576. (PhysTransmitDscr->FragPtr1.Fill << 16) |
  577. PhysTransmitDscr->FragPtr0.Fill
  578. );
  579. PktSize=CURRENT_DESCRIPTOR->ByteCount.Data;
  580. PktSize -=4; // don't check FCS field.
  581. for (i=0;i<PktSize;i++) {
  582. if (ReceivedMsg[i] != SentMsg[i]) {
  583. FwPrint("\r\n Data mismatch, expected %02lx received %02lx \r\n",SentMsg[i],ReceivedMsg[i]);
  584. SonicErrors++;
  585. return ERROR;
  586. }
  587. }
  588. //
  589. // If we get here is because the packet was successfully received.
  590. // Set the descriptor tables ready for the next packet.
  591. //
  592. if (ReceiveStatus & RCR_LPKT) { // last packet in RBA.
  593. //
  594. // Advance the RWP to free the used Rba again.
  595. //
  596. if (READ_REGISTER_USHORT(&SONIC->RWP.Reg)+sizeof(RECEIVE_RESOURCE) ==
  597. READ_REGISTER_USHORT(&SONIC->REA.Reg)) {//if it's the last one
  598. WRITE_REGISTER_USHORT(&SONIC->RWP.Reg,READ_REGISTER_USHORT(&SONIC->RSA.Reg));
  599. // the new RWP points at the starting address.
  600. } else {
  601. WRITE_REGISTER_USHORT(&SONIC->RWP.Reg,READ_REGISTER_USHORT(&SONIC->RWP.Reg)+sizeof(RECEIVE_RESOURCE));
  602. }
  603. }
  604. //
  605. // Free Used Receive Descripor
  606. //
  607. CURRENT_DESCRIPTOR->InUse.Data=AVAILABLE; // make used desc available
  608. ReceiveDscrQueue.Current=CURRENT_DESCRIPTOR->Link.Data; // First is the next
  609. LAST_DESCRIPTOR->Link.Data &= NOT_EOL; // Last is not EOL any more.
  610. ReceiveDscrQueue.Last=LAST_DESCRIPTOR->Link.Data; // Last is next one.
  611. LAST_DESCRIPTOR->InUse.Data |= EOL; // New Last is EOL.
  612. return DONE;
  613. }
  614. VOID
  615. RomXTOA(
  616. IN ULONG number,
  617. OUT PSZ string
  618. )
  619. /*++
  620. Routine Description:
  621. This routine converts an ULONG to ASCII.
  622. The conversion is done in HexaDecimal.
  623. Arguments:
  624. number - Supplies the ULONG to convert.
  625. string - PSZ where the result is placed.
  626. Return Value:
  627. None.
  628. --*/
  629. {
  630. ULONG i;
  631. for (i=7;i >= 0; i--) {
  632. string[i]=TranslationTable[number&0xF];
  633. number = number >> 4;
  634. }
  635. string[8]='\0';
  636. }
  637. ULONG
  638. RomSonicLoopBackTest(
  639. )
  640. /*++
  641. Routine Description:
  642. This routine implements the SONIC loopback test for the selftest.
  643. The Ethernet Controller is tested using a Loopback in the MAC.
  644. Arguments:
  645. None.
  646. Return Value:
  647. Returns 0 if no errors are found.
  648. --*/
  649. {
  650. //
  651. // Note Packets are set to be 32 byte long so that they fit in the fifo.
  652. // This is done because at this point interrupts are dispatched trough
  653. // the Bootstrap Vector, reads from PROM take so long that the SONIC
  654. // will get Bus retry Errors.
  655. //
  656. ULONG i,MsgLength=MIN_DATA_LENGTH-32;
  657. CHAR String[64];
  658. SonicErrors=0;
  659. InitSonic();
  660. if (SonicErrors) {
  661. return SonicErrors;
  662. }
  663. for (i=0;i<16;i++) {
  664. ComposeMessage(MsgLength,(UCHAR)i);
  665. SonicStatus.ExpectedInt=INT_TXDN | INT_PKTRX;
  666. // Issue the Transmit command.
  667. SonicIntSemaphore=1;
  668. WRITE_REGISTER_USHORT(&SONIC->Command.Reg,CR_TXP);
  669. if (WaitForSonicInterrupt()) {
  670. FwPrint("Timeout waiting for sonic int 2\r\n");
  671. SonicErrors++;
  672. return SonicErrors;
  673. }
  674. if (SonicStatus.Status==DONE) { // a packet has been sent and received.
  675. if (SonicCheckReception()==ERROR) {
  676. FwPrint(ST_RECEIVED_MSG);
  677. return SonicErrors;
  678. } else {
  679. FwPrint(".");
  680. }
  681. } else {
  682. SonicCheckError();
  683. FwPrint("\r\nInt:%x Tx:%x",SonicStatus.InterruptID,SonicStatus.TransmitControl);
  684. return SonicErrors;
  685. }
  686. }
  687. return SonicErrors;
  688. }