dwcethhw.c 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. dwcethhw.c
  5. Abstract:
  6. This module implements the actual hardware support for the DesignWare
  7. Ethernet controller.
  8. Author:
  9. Evan Green 5-Dec-2014
  10. Environment:
  11. Kernel
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <minoca/kernel/driver.h>
  17. #include <minoca/net/netdrv.h>
  18. #include <minoca/net/mii.h>
  19. #include "dwceth.h"
  20. //
  21. // ---------------------------------------------------------------- Definitions
  22. //
  23. //
  24. // Borrow an unused bit in the status register for the software link check.
  25. //
  26. #define DWE_STATUS_LINK_CHECK (1 << 11)
  27. //
  28. // Define the maximum amount of packets that DWE will keep queued before it
  29. // starts to drop packets.
  30. //
  31. #define DWE_MAX_TRANSMIT_PACKET_LIST_COUNT (DWE_TRANSMIT_DESCRIPTOR_COUNT * 2)
  32. //
  33. // ------------------------------------------------------ Data Type Definitions
  34. //
  35. //
  36. // ----------------------------------------------- Internal Function Prototypes
  37. //
  38. VOID
  39. DwepLinkCheckDpc (
  40. PDPC Dpc
  41. );
  42. KSTATUS
  43. DwepInitializePhy (
  44. PDWE_DEVICE Device
  45. );
  46. VOID
  47. DwepReadMacAddress (
  48. PDWE_DEVICE Device
  49. );
  50. VOID
  51. DwepReapCompletedTransmitDescriptors (
  52. PDWE_DEVICE Device
  53. );
  54. VOID
  55. DwepSendPendingPackets (
  56. PDWE_DEVICE Device
  57. );
  58. VOID
  59. DwepReapReceivedFrames (
  60. PDWE_DEVICE Device
  61. );
  62. KSTATUS
  63. DwepCheckLink (
  64. PDWE_DEVICE Device
  65. );
  66. KSTATUS
  67. DwepDetermineLinkParameters (
  68. PDWE_DEVICE Device,
  69. PBOOL LinkUp,
  70. PULONGLONG Speed,
  71. PBOOL FullDuplex
  72. );
  73. KSTATUS
  74. DwepReadMii (
  75. PDWE_DEVICE Device,
  76. ULONG Phy,
  77. ULONG Register,
  78. PULONG Result
  79. );
  80. KSTATUS
  81. DwepWriteMii (
  82. PDWE_DEVICE Device,
  83. ULONG Phy,
  84. ULONG Register,
  85. ULONG Value
  86. );
  87. //
  88. // -------------------------------------------------------------------- Globals
  89. //
  90. BOOL DweDisablePacketDropping = FALSE;
  91. //
  92. // ------------------------------------------------------------------ Functions
  93. //
  94. KSTATUS
  95. DweSend (
  96. PVOID DeviceContext,
  97. PNET_PACKET_LIST PacketList
  98. )
  99. /*++
  100. Routine Description:
  101. This routine sends data through the network.
  102. Arguments:
  103. DeviceContext - Supplies a pointer to the device context associated with
  104. the link down which this data is to be sent.
  105. PacketList - Supplies a pointer to a list of network packets to send. Data
  106. in these packets may be modified by this routine, but must not be used
  107. once this routine returns.
  108. Return Value:
  109. STATUS_SUCCESS if all packets were sent.
  110. STATUS_RESOURCE_IN_USE if some or all of the packets were dropped due to
  111. the hardware being backed up with too many packets to send.
  112. Other failure codes indicate that none of the packets were sent.
  113. --*/
  114. {
  115. PDWE_DEVICE Device;
  116. UINTN PacketListCount;
  117. KSTATUS Status;
  118. ASSERT(KeGetRunLevel() == RunLevelLow);
  119. Device = (PDWE_DEVICE)DeviceContext;
  120. KeAcquireQueuedLock(Device->TransmitLock);
  121. if (Device->LinkActive == FALSE) {
  122. Status = STATUS_NO_NETWORK_CONNECTION;
  123. goto SendEnd;
  124. }
  125. //
  126. // If there is any room in the packet list (or dropping packets is
  127. // disabled), add all of the packets to the list waiting to be sent.
  128. //
  129. PacketListCount = Device->TransmitPacketList.Count;
  130. if ((PacketListCount < DWE_MAX_TRANSMIT_PACKET_LIST_COUNT) ||
  131. (DweDisablePacketDropping != FALSE)) {
  132. NET_APPEND_PACKET_LIST(PacketList, &(Device->TransmitPacketList));
  133. DwepSendPendingPackets(Device);
  134. Status = STATUS_SUCCESS;
  135. //
  136. // Otherwise report that the resource is use as it is too busy to handle
  137. // more packets.
  138. //
  139. } else {
  140. Device->DroppedTxPackets += PacketList->Count;
  141. RtlDebugPrint("DWE: Dropped %d packets.\n", Device->DroppedTxPackets);
  142. Status = STATUS_RESOURCE_IN_USE;
  143. }
  144. SendEnd:
  145. KeReleaseQueuedLock(Device->TransmitLock);
  146. return Status;
  147. }
  148. KSTATUS
  149. DweGetSetInformation (
  150. PVOID DeviceContext,
  151. NET_LINK_INFORMATION_TYPE InformationType,
  152. PVOID Data,
  153. PUINTN DataSize,
  154. BOOL Set
  155. )
  156. /*++
  157. Routine Description:
  158. This routine gets or sets the network device layer's link information.
  159. Arguments:
  160. DeviceContext - Supplies a pointer to the device context associated with
  161. the link for which information is being set or queried.
  162. InformationType - Supplies the type of information being queried or set.
  163. Data - Supplies a pointer to the data buffer where the data is either
  164. returned for a get operation or given for a set operation.
  165. DataSize - Supplies a pointer that on input contains the size of the data
  166. buffer. On output, contains the required size of the data buffer.
  167. Set - Supplies a boolean indicating if this is a get operation (FALSE) or a
  168. set operation (TRUE).
  169. Return Value:
  170. Status code.
  171. --*/
  172. {
  173. ULONG ChangedFlags;
  174. PDWE_DEVICE Device;
  175. PULONG Flags;
  176. KSTATUS Status;
  177. ULONG Value;
  178. Device = DeviceContext;
  179. switch (InformationType) {
  180. case NetLinkInformationChecksumOffload:
  181. if (*DataSize != sizeof(ULONG)) {
  182. Status = STATUS_INVALID_PARAMETER;
  183. break;
  184. }
  185. //
  186. // If the request is a get, just return the device's current checksum
  187. // flags.
  188. //
  189. Status = STATUS_SUCCESS;
  190. Flags = (PULONG)Data;
  191. if (Set == FALSE) {
  192. *Flags = Device->ChecksumFlags;
  193. break;
  194. }
  195. //
  196. // Synchronize on the receive lock. There is nothing to do for transmit
  197. // changes, so leave that lock out of it.
  198. //
  199. KeAcquireQueuedLock(Device->ReceiveLock);
  200. //
  201. // If it is a set, figure out what is changing. There is nothing to do
  202. // if the change is in the transmit flags. Netcore requests transmit
  203. // offloads on a per-packet basis. Requests to enable or disable
  204. // receive checksum change the MAC configuration.
  205. //
  206. ChangedFlags = *Flags ^ Device->ChecksumFlags;
  207. if ((ChangedFlags & NET_LINK_CHECKSUM_FLAG_RECEIVE_MASK) != 0) {
  208. //
  209. // If any of the receive checksum flags are set, then
  210. // offloading must remain on for all protocols. There is no
  211. // granularity.
  212. //
  213. Value = DWE_READ(Device, DweRegisterMacConfiguration);
  214. if ((*Flags & NET_LINK_CHECKSUM_FLAG_RECEIVE_MASK) != 0) {
  215. Value |= DWE_MAC_CONFIGURATION_CHECKSUM_OFFLOAD;
  216. //
  217. // Otherwise, if all flags are off and something was previously
  218. // set, turn receive checksum offloadng off.
  219. //
  220. } else if ((*Flags & NET_LINK_CHECKSUM_FLAG_RECEIVE_MASK) == 0) {
  221. Value &= ~DWE_MAC_CONFIGURATION_CHECKSUM_OFFLOAD;
  222. }
  223. DWE_WRITE(Device, DweRegisterMacConfiguration, Value);
  224. }
  225. //
  226. // Update the checksum flags.
  227. //
  228. Device->ChecksumFlags = *Flags;
  229. KeReleaseQueuedLock(Device->ReceiveLock);
  230. break;
  231. default:
  232. Status = STATUS_NOT_SUPPORTED;
  233. break;
  234. }
  235. return Status;
  236. }
  237. KSTATUS
  238. DwepInitializeDeviceStructures (
  239. PDWE_DEVICE Device
  240. )
  241. /*++
  242. Routine Description:
  243. This routine creates the data structures needed for a DesignWare Ethernet
  244. controller.
  245. Arguments:
  246. Device - Supplies a pointer to the device.
  247. Return Value:
  248. Status code.
  249. --*/
  250. {
  251. ULONG AllocationSize;
  252. ULONG CommandIndex;
  253. PDWE_DESCRIPTOR Descriptor;
  254. ULONG DescriptorPhysical;
  255. ULONG DescriptorSize;
  256. ULONG FrameIndex;
  257. ULONG IoBufferFlags;
  258. ULONG NextDescriptorPhysical;
  259. ULONG ReceiveFrameData;
  260. ULONG ReceiveSize;
  261. KSTATUS Status;
  262. //
  263. // Initialize the transmit and receive list locks.
  264. //
  265. Device->TransmitLock = KeCreateQueuedLock();
  266. if (Device->TransmitLock == NULL) {
  267. Status = STATUS_INSUFFICIENT_RESOURCES;
  268. goto InitializeDeviceStructuresEnd;
  269. }
  270. Device->ReceiveLock = KeCreateQueuedLock();
  271. if (Device->ReceiveLock == NULL) {
  272. Status = STATUS_INSUFFICIENT_RESOURCES;
  273. goto InitializeDeviceStructuresEnd;
  274. }
  275. //
  276. // Allocate the receive buffers. This is allocated as non-write though and
  277. // cacheable, which means software must be careful when the frame is
  278. // first received (and do an invalidate), and when setting up the
  279. // link pointers, but after the receive is complete it's normal memory.
  280. //
  281. ReceiveSize = DWE_RECEIVE_FRAME_DATA_SIZE * DWE_RECEIVE_FRAME_COUNT;
  282. ASSERT(Device->ReceiveDataIoBuffer == NULL);
  283. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS;
  284. Device->ReceiveDataIoBuffer = MmAllocateNonPagedIoBuffer(0,
  285. MAX_ULONG,
  286. 16,
  287. ReceiveSize,
  288. IoBufferFlags);
  289. if (Device->ReceiveDataIoBuffer == NULL) {
  290. Status = STATUS_INSUFFICIENT_RESOURCES;
  291. goto InitializeDeviceStructuresEnd;
  292. }
  293. ASSERT(Device->ReceiveDataIoBuffer->FragmentCount == 1);
  294. ASSERT(Device->ReceiveDataIoBuffer->Fragment[0].VirtualAddress != NULL);
  295. Device->ReceiveData =
  296. Device->ReceiveDataIoBuffer->Fragment[0].VirtualAddress;
  297. //
  298. // Allocate both the transmit and the receive descriptors. This is
  299. // allocated non-cached as they are shared with the hardware.
  300. //
  301. DescriptorSize = (DWE_TRANSMIT_DESCRIPTOR_COUNT + DWE_RECEIVE_FRAME_COUNT) *
  302. sizeof(DWE_DESCRIPTOR);
  303. ASSERT(Device->DescriptorIoBuffer == NULL);
  304. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS;
  305. Device->DescriptorIoBuffer = MmAllocateNonPagedIoBuffer(0,
  306. MAX_ULONG,
  307. 16,
  308. DescriptorSize,
  309. IoBufferFlags);
  310. if (Device->DescriptorIoBuffer == NULL) {
  311. Status = STATUS_INSUFFICIENT_RESOURCES;
  312. goto InitializeDeviceStructuresEnd;
  313. }
  314. ASSERT(Device->DescriptorIoBuffer->FragmentCount == 1);
  315. ASSERT(Device->DescriptorIoBuffer->Fragment[0].VirtualAddress != NULL);
  316. Device->TransmitDescriptors =
  317. Device->DescriptorIoBuffer->Fragment[0].VirtualAddress;
  318. Device->ReceiveDescriptors = Device->TransmitDescriptors +
  319. DWE_TRANSMIT_DESCRIPTOR_COUNT;
  320. NET_INITIALIZE_PACKET_LIST(&(Device->TransmitPacketList));
  321. Device->TransmitBegin = 0;
  322. Device->TransmitEnd = 0;
  323. Device->ReceiveBegin = 0;
  324. RtlZeroMemory(Device->TransmitDescriptors, DescriptorSize);
  325. //
  326. // Allocate an array of pointers to net packet buffers that runs parallel
  327. // to the transmit array.
  328. //
  329. AllocationSize = sizeof(PNET_PACKET_BUFFER) * DWE_TRANSMIT_DESCRIPTOR_COUNT;
  330. Device->TransmitPacket = MmAllocateNonPagedPool(AllocationSize,
  331. DWE_ALLOCATION_TAG);
  332. if (Device->TransmitPacket == NULL) {
  333. Status = STATUS_INSUFFICIENT_RESOURCES;
  334. goto InitializeDeviceStructuresEnd;
  335. }
  336. RtlZeroMemory(Device->TransmitPacket, AllocationSize);
  337. ASSERT(Device->WorkItem == NULL);
  338. Device->WorkItem = KeCreateWorkItem(
  339. NULL,
  340. WorkPriorityNormal,
  341. (PWORK_ITEM_ROUTINE)DwepInterruptServiceWorker,
  342. Device,
  343. DWE_ALLOCATION_TAG);
  344. if (Device->WorkItem == NULL) {
  345. Status = STATUS_INSUFFICIENT_RESOURCES;
  346. goto InitializeDeviceStructuresEnd;
  347. }
  348. ASSERT(Device->LinkCheckTimer == NULL);
  349. Device->LinkCheckTimer = KeCreateTimer(DWE_ALLOCATION_TAG);
  350. if (Device->LinkCheckTimer == NULL) {
  351. Status = STATUS_INSUFFICIENT_RESOURCES;
  352. goto InitializeDeviceStructuresEnd;
  353. }
  354. Device->LinkCheckDpc = KeCreateDpc(DwepLinkCheckDpc, Device);
  355. if (Device->LinkCheckDpc == NULL) {
  356. Status = STATUS_INSUFFICIENT_RESOURCES;
  357. goto InitializeDeviceStructuresEnd;
  358. }
  359. //
  360. // Initialize the receive frame list in chained mode.
  361. //
  362. DescriptorPhysical =
  363. (ULONG)(Device->DescriptorIoBuffer->Fragment[0].PhysicalAddress);
  364. DescriptorPhysical += sizeof(DWE_DESCRIPTOR) *
  365. DWE_TRANSMIT_DESCRIPTOR_COUNT;
  366. NextDescriptorPhysical = DescriptorPhysical + sizeof(DWE_DESCRIPTOR);
  367. ReceiveFrameData =
  368. (ULONG)(Device->ReceiveDataIoBuffer->Fragment[0].PhysicalAddress);
  369. for (FrameIndex = 0;
  370. FrameIndex < DWE_RECEIVE_FRAME_COUNT;
  371. FrameIndex += 1) {
  372. Descriptor = &(Device->ReceiveDescriptors[FrameIndex]);
  373. Descriptor->Control = DWE_RX_STATUS_DMA_OWNED;
  374. Descriptor->BufferSize =
  375. DWE_BUFFER_SIZE(DWE_RECEIVE_FRAME_DATA_SIZE, 0) |
  376. DWE_RX_SIZE_CHAINED;
  377. Descriptor->Address1 = ReceiveFrameData;
  378. ReceiveFrameData += DWE_RECEIVE_FRAME_DATA_SIZE;
  379. if (FrameIndex == DWE_RECEIVE_FRAME_COUNT - 1) {
  380. Descriptor->Address2OrNextDescriptor = DescriptorPhysical;
  381. } else {
  382. Descriptor->Address2OrNextDescriptor = NextDescriptorPhysical;
  383. }
  384. NextDescriptorPhysical += sizeof(DWE_DESCRIPTOR);
  385. }
  386. //
  387. // Initialize the transmit descriptor list in chained mode. The "DMA owned"
  388. // bit is clear on all descriptors, so the controller doesn't try to
  389. // transmit them.
  390. //
  391. DescriptorPhysical =
  392. (ULONG)(Device->DescriptorIoBuffer->Fragment[0].PhysicalAddress);
  393. NextDescriptorPhysical = DescriptorPhysical + sizeof(DWE_DESCRIPTOR);
  394. for (CommandIndex = 0;
  395. CommandIndex < DWE_TRANSMIT_DESCRIPTOR_COUNT;
  396. CommandIndex += 1) {
  397. Descriptor = &(Device->TransmitDescriptors[CommandIndex]);
  398. Descriptor->Control = DWE_TX_CONTROL_CHAINED;
  399. //
  400. // Loop the last command back around to the first.
  401. //
  402. if (CommandIndex == DWE_TRANSMIT_DESCRIPTOR_COUNT - 1) {
  403. Descriptor->Address2OrNextDescriptor = DescriptorPhysical;
  404. //
  405. // Point this link at the next command.
  406. //
  407. } else {
  408. Descriptor->Address2OrNextDescriptor = NextDescriptorPhysical;
  409. }
  410. NextDescriptorPhysical += sizeof(DWE_DESCRIPTOR);
  411. }
  412. Status = STATUS_SUCCESS;
  413. InitializeDeviceStructuresEnd:
  414. if (!KSUCCESS(Status)) {
  415. if (Device->TransmitLock != NULL) {
  416. KeDestroyQueuedLock(Device->TransmitLock);
  417. Device->TransmitLock = NULL;
  418. }
  419. if (Device->ReceiveLock != NULL) {
  420. KeDestroyQueuedLock(Device->ReceiveLock);
  421. Device->ReceiveLock = NULL;
  422. }
  423. if (Device->ReceiveDataIoBuffer != NULL) {
  424. MmFreeIoBuffer(Device->ReceiveDataIoBuffer);
  425. Device->ReceiveDataIoBuffer = NULL;
  426. Device->ReceiveData = NULL;
  427. }
  428. if (Device->DescriptorIoBuffer != NULL) {
  429. MmFreeIoBuffer(Device->DescriptorIoBuffer);
  430. Device->DescriptorIoBuffer = NULL;
  431. Device->TransmitDescriptors = NULL;
  432. Device->ReceiveDescriptors = NULL;
  433. }
  434. if (Device->TransmitPacket != NULL) {
  435. MmFreeNonPagedPool(Device->TransmitPacket);
  436. Device->TransmitPacket = NULL;
  437. }
  438. if (Device->WorkItem != NULL) {
  439. KeDestroyWorkItem(Device->WorkItem);
  440. Device->WorkItem = NULL;
  441. }
  442. if (Device->LinkCheckTimer != NULL) {
  443. KeDestroyTimer(Device->LinkCheckTimer);
  444. Device->LinkCheckTimer = NULL;
  445. }
  446. if (Device->LinkCheckDpc != NULL) {
  447. KeDestroyDpc(Device->LinkCheckDpc);
  448. Device->LinkCheckDpc = NULL;
  449. }
  450. }
  451. return Status;
  452. }
  453. KSTATUS
  454. DwepResetDevice (
  455. PDWE_DEVICE Device
  456. )
  457. /*++
  458. Routine Description:
  459. This routine resets the DesignWare Ethernet device.
  460. Arguments:
  461. Device - Supplies a pointer to the device.
  462. Return Value:
  463. Status code.
  464. --*/
  465. {
  466. ULONG DescriptorBase;
  467. ULONGLONG Frequency;
  468. KSTATUS Status;
  469. ULONGLONG Timeout;
  470. ULONG Value;
  471. //
  472. // Read the MAC address before resetting the device to get a MAC address
  473. // that might have been assigned by the firmware.
  474. //
  475. DwepReadMacAddress(Device);
  476. //
  477. // Perform a software reset, and wait for it to finish.
  478. //
  479. Value = DWE_READ(Device, DweRegisterBusMode);
  480. Value |= DWE_BUS_MODE_SOFTWARE_RESET;
  481. DWE_WRITE(Device, DweRegisterBusMode, Value);
  482. Frequency = HlQueryTimeCounterFrequency();
  483. Timeout = KeGetRecentTimeCounter() + Frequency;
  484. do {
  485. Value = DWE_READ(Device, DweRegisterBusMode);
  486. if ((Value & DWE_BUS_MODE_SOFTWARE_RESET) == 0) {
  487. break;
  488. }
  489. KeYield();
  490. } while (KeGetRecentTimeCounter() <= Timeout);
  491. if ((Value & DWE_BUS_MODE_SOFTWARE_RESET) != 0) {
  492. RtlDebugPrint("DWE: Cannot reset device.\n");
  493. return STATUS_DEVICE_IO_ERROR;
  494. }
  495. Value |= DWE_BUS_MODE_LARGE_DESCRIPTORS |
  496. DWE_BUS_MODE_8X_BURST_LENGTHS |
  497. (DWE_BUS_MODE_TX_BURST_LENGTH <<
  498. DWE_BUS_MODE_TX_BURST_LENGTH_SHIFT);
  499. DWE_WRITE(Device, DweRegisterBusMode, Value);
  500. //
  501. // Halt any DMA.
  502. //
  503. Value = DWE_READ(Device, DweRegisterOperationMode);
  504. Value &= ~(DWE_OPERATION_MODE_START_RECEIVE |
  505. DWE_OPERATION_MODE_START_TRANSMIT);
  506. DWE_WRITE(Device, DweRegisterOperationMode, Value);
  507. //
  508. // Write the descriptor base addresses.
  509. //
  510. DescriptorBase =
  511. (ULONG)(Device->DescriptorIoBuffer->Fragment[0].PhysicalAddress);
  512. DWE_WRITE(Device, DweRegisterTransmitDescriptorListAddress, DescriptorBase);
  513. DescriptorBase += sizeof(DWE_DESCRIPTOR) * DWE_TRANSMIT_DESCRIPTOR_COUNT;
  514. DWE_WRITE(Device, DweRegisterReceiveDescriptorListAddress, DescriptorBase);
  515. //
  516. // Set the MAC address.
  517. //
  518. RtlCopyMemory(&Value, Device->MacAddress, sizeof(ULONG));
  519. DWE_WRITE(Device, DWE_MAC_ADDRESS_LOW(0), Value);
  520. Value = 0;
  521. RtlCopyMemory(&Value, &(Device->MacAddress[sizeof(ULONG)]), sizeof(USHORT));
  522. DWE_WRITE(Device, DWE_MAC_ADDRESS_HIGH(0), Value);
  523. Value = DWE_MAC_FRAME_FILTER_HASH_MULTICAST;
  524. DWE_WRITE(Device, DweRegisterMacFrameFilter, Value);
  525. //
  526. // Set up DMA.
  527. //
  528. Value = DWE_READ(Device, DweRegisterOperationMode);
  529. Value |= DWE_OPERATION_MODE_TX_STORE_AND_FORWARD |
  530. DWE_OPERATION_MODE_OPERATE_ON_SECOND_FRAME |
  531. DWE_OPERATION_MODE_FORWARD_UNDERSIZED_GOOD_FRAMES |
  532. DWE_OPERATION_MODE_RX_THRESHOLD_32;
  533. Value &= ~DWE_OPERATION_MODE_RX_STORE_AND_FORWARD;
  534. DWE_WRITE(Device, DweRegisterOperationMode, Value);
  535. DWE_WRITE(Device, DweRegisterInterruptEnable, DWE_INTERRUPT_ENABLE_DEFAULT);
  536. //
  537. // Disable interrupts that indicate when the counters get halfway or all
  538. // the way towards overflowing.
  539. //
  540. Value = DWE_RECEIVE_INTERRUPT_MASK;
  541. DWE_WRITE(Device, DweRegisterMmcReceiveInterruptMask, Value);
  542. Value = DWE_TRANSMIT_INTERRUPT_MASK;
  543. DWE_WRITE(Device, DweRegisterMmcTransmitInterruptMask, Value);
  544. Value = DWE_RECEIVE_CHECKSUM_INTERRUPT_MASK;
  545. DWE_WRITE(Device, DweRegisterReceiveChecksumOffloadInterruptMask, Value);
  546. //
  547. // Fire up DMA.
  548. //
  549. Value = DWE_READ(Device, DweRegisterOperationMode);
  550. Value |= DWE_OPERATION_MODE_START_TRANSMIT |
  551. DWE_OPERATION_MODE_START_RECEIVE;
  552. DWE_WRITE(Device, DweRegisterOperationMode, Value);
  553. //
  554. // Enable data flow.
  555. //
  556. Value = DWE_READ(Device, DweRegisterMacConfiguration);
  557. Value |= DWE_MAC_CONFIGURATION_JABBER_DISABLE |
  558. DWE_MAC_CONFIGURATION_AUTO_PAD_CRC_STRIPPING |
  559. DWE_MAC_CONFIGURATION_BURST_ENABLE |
  560. DWE_MAC_CONFIGURATION_TRANSMITTER_ENABLE |
  561. DWE_MAC_CONFIGURATION_RECEIVER_ENABLE;
  562. if ((Device->ChecksumFlags & NET_LINK_CHECKSUM_FLAG_RECEIVE_MASK) != 0) {
  563. Value |= DWE_MAC_CONFIGURATION_CHECKSUM_OFFLOAD;
  564. } else {
  565. Value &= ~DWE_MAC_CONFIGURATION_CHECKSUM_OFFLOAD;
  566. }
  567. DWE_WRITE(Device, DweRegisterMacConfiguration, Value);
  568. Status = DwepInitializePhy(Device);
  569. if (!KSUCCESS(Status)) {
  570. goto ResetDeviceEnd;
  571. }
  572. //
  573. // Notify the networking core of this new link now that the device is ready
  574. // to send and receive data, pending media being present.
  575. //
  576. if (Device->NetworkLink == NULL) {
  577. Status = DwepAddNetworkDevice(Device);
  578. if (!KSUCCESS(Status)) {
  579. goto ResetDeviceEnd;
  580. }
  581. }
  582. //
  583. // Determine whether or not there is media connected, and what speed it is.
  584. //
  585. Status = DwepCheckLink(Device);
  586. if (!KSUCCESS(Status)) {
  587. goto ResetDeviceEnd;
  588. }
  589. //
  590. // Fire up the link check timer.
  591. //
  592. Device->LinkCheckInterval = Frequency * DWE_LINK_CHECK_INTERVAL;
  593. KeQueueTimer(Device->LinkCheckTimer,
  594. TimerQueueSoft,
  595. 0,
  596. Device->LinkCheckInterval,
  597. 0,
  598. Device->LinkCheckDpc);
  599. ResetDeviceEnd:
  600. return Status;
  601. }
  602. INTERRUPT_STATUS
  603. DwepInterruptService (
  604. PVOID Context
  605. )
  606. /*++
  607. Routine Description:
  608. This routine implements the DesignWare Ethernet interrupt service routine.
  609. Arguments:
  610. Context - Supplies the context pointer given to the system when the
  611. interrupt was connected. In this case, this points to the e100 device
  612. structure.
  613. Return Value:
  614. Interrupt status.
  615. --*/
  616. {
  617. PDWE_DEVICE Device;
  618. INTERRUPT_STATUS InterruptStatus;
  619. ULONG PendingBits;
  620. Device = (PDWE_DEVICE)Context;
  621. InterruptStatus = InterruptStatusNotClaimed;
  622. //
  623. // Read the status register, and if anything's set add it to the pending
  624. // bits.
  625. //
  626. PendingBits = DWE_READ(Device, DweRegisterStatus);
  627. if (PendingBits != 0) {
  628. InterruptStatus = InterruptStatusClaimed;
  629. RtlAtomicOr32(&(Device->PendingStatusBits), PendingBits);
  630. //
  631. // Read the more detailed status register, and clear the bits.
  632. //
  633. DWE_WRITE(Device, DweRegisterStatus, PendingBits);
  634. if ((PendingBits & DWE_STATUS_ERROR_MASK) != 0) {
  635. RtlDebugPrint("DWE Error: %08x\n", PendingBits);
  636. }
  637. }
  638. return InterruptStatus;
  639. }
  640. INTERRUPT_STATUS
  641. DwepInterruptServiceWorker (
  642. PVOID Parameter
  643. )
  644. /*++
  645. Routine Description:
  646. This routine processes interrupts for the DesignWare Ethernet controller at
  647. low level.
  648. Arguments:
  649. Parameter - Supplies an optional parameter passed in by the creator of the
  650. work item.
  651. Return Value:
  652. Interrupt status.
  653. --*/
  654. {
  655. ULONGLONG CurrentTime;
  656. PDWE_DEVICE Device;
  657. ULONG PendingBits;
  658. Device = (PDWE_DEVICE)(Parameter);
  659. ASSERT(KeGetRunLevel() == RunLevelLow);
  660. //
  661. // Clear out the pending bits.
  662. //
  663. PendingBits = RtlAtomicExchange32(&(Device->PendingStatusBits), 0);
  664. if (PendingBits == 0) {
  665. return InterruptStatusNotClaimed;
  666. }
  667. if ((PendingBits & DWE_STATUS_RECEIVE_INTERRUPT) != 0) {
  668. DwepReapReceivedFrames(Device);
  669. }
  670. //
  671. // If the command unit finished what it was up to, reap that memory.
  672. //
  673. if ((PendingBits & DWE_STATUS_TRANSMIT_INTERRUPT) != 0) {
  674. DwepReapCompletedTransmitDescriptors(Device);
  675. }
  676. if ((PendingBits & DWE_STATUS_LINK_CHECK) != 0) {
  677. CurrentTime = KeGetRecentTimeCounter();
  678. Device->NextLinkCheck = CurrentTime + Device->LinkCheckInterval;
  679. DwepCheckLink(Device);
  680. }
  681. return InterruptStatusClaimed;
  682. }
  683. //
  684. // --------------------------------------------------------- Internal Functions
  685. //
  686. VOID
  687. DwepLinkCheckDpc (
  688. PDPC Dpc
  689. )
  690. /*++
  691. Routine Description:
  692. This routine implements the DesignWare Ethernet DPC that is queued when an
  693. interrupt fires.
  694. Arguments:
  695. Dpc - Supplies a pointer to the DPC that is running.
  696. Return Value:
  697. None.
  698. --*/
  699. {
  700. PDWE_DEVICE Device;
  701. ULONG OldPendingStatus;
  702. KSTATUS Status;
  703. Device = (PDWE_DEVICE)(Dpc->UserData);
  704. OldPendingStatus = RtlAtomicOr32(&(Device->PendingStatusBits),
  705. DWE_STATUS_LINK_CHECK);
  706. if ((OldPendingStatus & DWE_STATUS_LINK_CHECK) == 0) {
  707. Status = KeQueueWorkItem(Device->WorkItem);
  708. if (!KSUCCESS(Status)) {
  709. RtlAtomicAnd32(&(Device->PendingStatusBits),
  710. ~DWE_STATUS_LINK_CHECK);
  711. }
  712. }
  713. return;
  714. }
  715. KSTATUS
  716. DwepInitializePhy (
  717. PDWE_DEVICE Device
  718. )
  719. /*++
  720. Routine Description:
  721. This routine initializes the PHY on the DesignWare Ethernet Controller.
  722. Arguments:
  723. Device - Supplies a pointer to the device.
  724. Return Value:
  725. Status code.
  726. --*/
  727. {
  728. ULONG BasicStatus;
  729. ULONG PhyId;
  730. KSTATUS Status;
  731. ULONG Value;
  732. //
  733. // Find the PHY.
  734. //
  735. Device->PhyId = (ULONG)-1;
  736. for (PhyId = 0; PhyId < MII_PHY_COUNT; PhyId += 1) {
  737. BasicStatus = 0;
  738. Status = DwepReadMii(Device,
  739. PhyId,
  740. MiiRegisterBasicStatus,
  741. &BasicStatus);
  742. //
  743. // If the register presents at least one of the connection
  744. // possibilities, then assume its valid.
  745. //
  746. if ((KSUCCESS(Status)) && (BasicStatus != 0) &&
  747. (BasicStatus != MAX_USHORT) &&
  748. ((BasicStatus &
  749. (MII_BASIC_STATUS_MEDIA_MASK |
  750. MII_BASIC_STATUS_EXTENDED_STATUS)) != 0)) {
  751. Device->PhyId = PhyId;
  752. break;
  753. }
  754. }
  755. //
  756. // If no PHY was found, fail to start.
  757. //
  758. if (Device->PhyId == (ULONG)-1) {
  759. Status = STATUS_NO_SUCH_DEVICE;
  760. return Status;
  761. }
  762. //
  763. // TODO: This should be in generic MII code.
  764. //
  765. Status = DwepWriteMii(Device,
  766. Device->PhyId,
  767. MiiRegisterBasicControl,
  768. MII_BASIC_CONTROL_RESET);
  769. if (!KSUCCESS(Status)) {
  770. return Status;
  771. }
  772. Value = MII_ADVERTISE_ALL | MII_ADVERTISE_CSMA | MII_ADVERTISE_PAUSE |
  773. MII_ADVERTISE_PAUSE_ASYMMETRIC;
  774. Status = DwepWriteMii(Device, Device->PhyId, MiiRegisterAdvertise, Value);
  775. if (!KSUCCESS(Status)) {
  776. return Status;
  777. }
  778. return Status;
  779. }
  780. VOID
  781. DwepReadMacAddress (
  782. PDWE_DEVICE Device
  783. )
  784. /*++
  785. Routine Description:
  786. This routine reads the current MAC address out of the DesignWare Ethernet
  787. controller.
  788. Arguments:
  789. Device - Supplies a pointer to the device.
  790. Return Value:
  791. None.
  792. --*/
  793. {
  794. ULONG AddressHigh;
  795. ULONG AddressLow;
  796. if (Device->MacAddressAssigned != FALSE) {
  797. return;
  798. }
  799. AddressLow = DWE_READ(Device, DWE_MAC_ADDRESS_LOW(0));
  800. AddressHigh = DWE_READ(Device, DWE_MAC_ADDRESS_HIGH(0)) & 0x0000FFFF;
  801. if ((AddressLow != 0xFFFFFFFF) || (AddressHigh != 0x0000FFFF)) {
  802. RtlCopyMemory(Device->MacAddress, &AddressLow, sizeof(ULONG));
  803. RtlCopyMemory(&(Device->MacAddress[sizeof(ULONG)]),
  804. &AddressHigh,
  805. sizeof(USHORT));
  806. } else {
  807. NetCreateEthernetAddress(Device->MacAddress);
  808. }
  809. Device->MacAddressAssigned = TRUE;
  810. return;
  811. }
  812. VOID
  813. DwepReapCompletedTransmitDescriptors (
  814. PDWE_DEVICE Device
  815. )
  816. /*++
  817. Routine Description:
  818. This routine cleans out any transmit descriptors completed by the hardware.
  819. This routine must be called at low level and assumes the command list lock
  820. is already held.
  821. Arguments:
  822. Device - Supplies a pointer to the device.
  823. Return Value:
  824. None.
  825. --*/
  826. {
  827. UINTN Begin;
  828. PDWE_DESCRIPTOR Descriptor;
  829. BOOL DescriptorReaped;
  830. DescriptorReaped = FALSE;
  831. KeAcquireQueuedLock(Device->TransmitLock);
  832. while (TRUE) {
  833. Begin = Device->TransmitBegin;
  834. Descriptor = &(Device->TransmitDescriptors[Begin]);
  835. //
  836. // If the buffer size word is zeroed, that's the indication that this
  837. // descriptor has already been cleaned out.
  838. //
  839. if (Descriptor->BufferSize == 0) {
  840. break;
  841. }
  842. //
  843. // If the command, whatever it may be, is not complete, then this is
  844. // an active entry, so stop reaping.
  845. //
  846. if ((Descriptor->Control & DWE_TX_CONTROL_DMA_OWNED) != 0) {
  847. break;
  848. }
  849. if ((Descriptor->Control & DWE_TX_CONTROL_ERROR_MASK) != 0) {
  850. RtlDebugPrint("DWE: TX Error %x\n", Descriptor->Control);
  851. }
  852. //
  853. // Free up the packet and mark the descriptor as free for use by
  854. // zeroing out the control.
  855. //
  856. NetFreeBuffer(Device->TransmitPacket[Begin]);
  857. Device->TransmitPacket[Begin] = NULL;
  858. Descriptor->BufferSize = 0;
  859. DescriptorReaped = TRUE;
  860. //
  861. // Move the beginning of the list forward.
  862. //
  863. if (Begin == DWE_TRANSMIT_DESCRIPTOR_COUNT - 1) {
  864. Device->TransmitBegin = 0;
  865. } else {
  866. Device->TransmitBegin = Begin + 1;
  867. }
  868. }
  869. if (DescriptorReaped != FALSE) {
  870. DwepSendPendingPackets(Device);
  871. }
  872. KeReleaseQueuedLock(Device->TransmitLock);
  873. return;
  874. }
  875. VOID
  876. DwepSendPendingPackets (
  877. PDWE_DEVICE Device
  878. )
  879. /*++
  880. Routine Description:
  881. This routine sends as many packets as can fit in the hardware descriptor
  882. buffer. This routine assumes the transmit lock is already held.
  883. Arguments:
  884. Device - Supplies a pointer to the device.
  885. Return Value:
  886. None.
  887. --*/
  888. {
  889. PHYSICAL_ADDRESS BufferPhysical;
  890. ULONG Control;
  891. PDWE_DESCRIPTOR Descriptor;
  892. ULONG DescriptorIndex;
  893. PNET_PACKET_BUFFER Packet;
  894. BOOL PacketSent;
  895. ULONG PacketSize;
  896. //
  897. // Send as many packets as possible.
  898. //
  899. PacketSent = FALSE;
  900. while (NET_PACKET_LIST_EMPTY(&(Device->TransmitPacketList)) == FALSE) {
  901. Packet = LIST_VALUE(Device->TransmitPacketList.Head.Next,
  902. NET_PACKET_BUFFER,
  903. ListEntry);
  904. DescriptorIndex = Device->TransmitEnd;
  905. Descriptor = &(Device->TransmitDescriptors[DescriptorIndex]);
  906. if (Descriptor->BufferSize != 0) {
  907. break;
  908. }
  909. NET_REMOVE_PACKET_FROM_LIST(Packet, &(Device->TransmitPacketList));
  910. //
  911. // Success, a free descriptor. Let's fill it out!
  912. //
  913. Control = DWE_TX_CONTROL_CHAINED |
  914. DWE_TX_CONTROL_FIRST_SEGMENT |
  915. DWE_TX_CONTROL_LAST_SEGMENT |
  916. DWE_TX_CONTROL_INTERRUPT_ON_COMPLETE |
  917. DWE_TX_CONTROL_CHECKSUM_NONE |
  918. DWE_TX_CONTROL_DMA_OWNED;
  919. if ((Packet->Flags & NET_PACKET_FLAG_IP_CHECKSUM_OFFLOAD) != 0) {
  920. if ((Packet->Flags &
  921. (NET_PACKET_FLAG_TCP_CHECKSUM_OFFLOAD |
  922. NET_PACKET_FLAG_UDP_CHECKSUM_OFFLOAD)) != 0) {
  923. Control |= DWE_TX_CONTROL_CHECKSUM_PSEUDOHEADER;
  924. } else {
  925. Control |= DWE_TX_CONTROL_CHECKSUM_IP_HEADER;
  926. }
  927. }
  928. //
  929. // Fill out the transfer buffer pointer and size.
  930. //
  931. PacketSize = Packet->FooterOffset - Packet->DataOffset;
  932. Descriptor->BufferSize = DWE_BUFFER_SIZE(PacketSize, 0);
  933. BufferPhysical = Packet->BufferPhysicalAddress + Packet->DataOffset;
  934. ASSERT(BufferPhysical == (ULONG)BufferPhysical);
  935. Descriptor->Address1 = BufferPhysical;
  936. Device->TransmitPacket[DescriptorIndex] = Packet;
  937. //
  938. // Use a register write to write the new control value in, making
  939. // it live in the hardware.
  940. //
  941. HlWriteRegister32(&(Descriptor->Control), Control);
  942. //
  943. // Move the pointer past this entry.
  944. //
  945. if (DescriptorIndex == DWE_TRANSMIT_DESCRIPTOR_COUNT - 1) {
  946. Device->TransmitEnd = 0;
  947. } else {
  948. Device->TransmitEnd = DescriptorIndex + 1;
  949. }
  950. PacketSent = TRUE;
  951. }
  952. //
  953. // Write the transmit poll demand register to make the hardware take a look
  954. // at the transmit queue again.
  955. //
  956. if (PacketSent != FALSE) {
  957. DWE_WRITE(Device, DweRegisterTransmitPollDemand, 1);
  958. }
  959. return;
  960. }
  961. VOID
  962. DwepReapReceivedFrames (
  963. PDWE_DEVICE Device
  964. )
  965. /*++
  966. Routine Description:
  967. This routine processes any received frames from the network.
  968. Arguments:
  969. Device - Supplies a pointer to the device.
  970. Return Value:
  971. None.
  972. --*/
  973. {
  974. UINTN Begin;
  975. PDWE_DESCRIPTOR Descriptor;
  976. ULONG ExtendedStatus;
  977. NET_PACKET_BUFFER Packet;
  978. ULONG PayloadType;
  979. ULONG ReceivePhysical;
  980. PVOID ReceiveVirtual;
  981. ASSERT(KeGetRunLevel() == RunLevelLow);
  982. //
  983. // Loop grabbing completed frames.
  984. //
  985. Packet.Flags = 0;
  986. KeAcquireQueuedLock(Device->ReceiveLock);
  987. ReceivePhysical =
  988. (ULONG)(Device->ReceiveDataIoBuffer->Fragment[0].PhysicalAddress);
  989. ReceiveVirtual = Device->ReceiveDataIoBuffer->Fragment[0].VirtualAddress;
  990. while (TRUE) {
  991. Begin = Device->ReceiveBegin;
  992. Descriptor = &(Device->ReceiveDescriptors[Begin]);
  993. //
  994. // If the frame is not complete, then this is the end of packets that
  995. // need to be reaped.
  996. //
  997. if ((Descriptor->Control & DWE_RX_STATUS_DMA_OWNED) != 0) {
  998. break;
  999. }
  1000. //
  1001. // If the frame came through alright, send it up to the core networking
  1002. // library to process.
  1003. //
  1004. if ((Descriptor->Control & DWE_RX_STATUS_ERROR_MASK) == 0) {
  1005. Packet.Buffer = ReceiveVirtual +
  1006. (Begin * DWE_RECEIVE_FRAME_DATA_SIZE);
  1007. Packet.BufferPhysicalAddress =
  1008. ReceivePhysical + (Begin * DWE_RECEIVE_FRAME_DATA_SIZE);
  1009. Packet.BufferSize = (Descriptor->Control >>
  1010. DWE_RX_STATUS_FRAME_LENGTH_SHIFT) &
  1011. DWE_RX_STATUS_FRAME_LENGTH_MASK;
  1012. Packet.DataSize = Packet.BufferSize;
  1013. Packet.DataOffset = 0;
  1014. Packet.FooterOffset = Packet.DataSize;
  1015. Packet.Flags = 0;
  1016. //
  1017. // If receive checksum offloading is enabled, figure out how to set
  1018. // the packet checksum offload flags.
  1019. //
  1020. if ((Device->ChecksumFlags &
  1021. NET_LINK_CHECKSUM_FLAG_RECEIVE_MASK) != 0) {
  1022. if ((Descriptor->Control &
  1023. DWE_RX_STATUS_EXTENDED_STATUS) != 0) {
  1024. ExtendedStatus = Descriptor->ExtendedStatus;
  1025. //
  1026. // If an IP header error occurred, leave it at that.
  1027. //
  1028. if ((ExtendedStatus &
  1029. DWE_RX_STATUS2_IP_HEADER_ERROR) != 0) {
  1030. Packet.Flags |= NET_PACKET_FLAG_IP_CHECKSUM_OFFLOAD |
  1031. NET_PACKET_FLAG_IP_CHECKSUM_FAILED;
  1032. //
  1033. // If the checksum was not bypassed, then the IP header
  1034. // checksum was valid.
  1035. //
  1036. } else if ((ExtendedStatus &
  1037. DWE_RX_STATUS2_IP_CHECKSUM_BYPASSED) == 0) {
  1038. Packet.Flags |= NET_PACKET_FLAG_IP_CHECKSUM_OFFLOAD;
  1039. PayloadType = ExtendedStatus &
  1040. DWE_RX_STATUS2_IP_PAYLOAD_TYPE_MASK;
  1041. //
  1042. // Handle a TCP packet.
  1043. //
  1044. if (PayloadType == DWE_RX_STATUS2_IP_PAYLOAD_TCP) {
  1045. Packet.Flags |=
  1046. NET_PACKET_FLAG_TCP_CHECKSUM_OFFLOAD;
  1047. if ((ExtendedStatus &
  1048. DWE_RX_STATUS2_IP_PAYLOAD_ERROR) != 0) {
  1049. Packet.Flags |=
  1050. NET_PACKET_FLAG_TCP_CHECKSUM_FAILED;
  1051. }
  1052. //
  1053. // Handle a UDP packet.
  1054. //
  1055. } else if (PayloadType ==
  1056. DWE_RX_STATUS2_IP_PAYLOAD_UDP) {
  1057. Packet.Flags |=
  1058. NET_PACKET_FLAG_UDP_CHECKSUM_OFFLOAD;
  1059. if ((ExtendedStatus &
  1060. DWE_RX_STATUS2_IP_PAYLOAD_ERROR) != 0) {
  1061. Packet.Flags |=
  1062. NET_PACKET_FLAG_UDP_CHECKSUM_FAILED;
  1063. }
  1064. }
  1065. }
  1066. }
  1067. }
  1068. NetProcessReceivedPacket(Device->NetworkLink, &Packet);
  1069. } else {
  1070. RtlDebugPrint("DWE: RX Error %08x\n", Descriptor->Control);
  1071. }
  1072. //
  1073. // Set this frame up to be reused, it will be the new end of the list.
  1074. //
  1075. HlWriteRegister32(&(Descriptor->Control), DWE_RX_STATUS_DMA_OWNED);
  1076. //
  1077. // Move the beginning pointer up.
  1078. //
  1079. if (Begin == DWE_RECEIVE_FRAME_COUNT - 1) {
  1080. Device->ReceiveBegin = 0;
  1081. } else {
  1082. Device->ReceiveBegin = Begin + 1;
  1083. }
  1084. }
  1085. KeReleaseQueuedLock(Device->ReceiveLock);
  1086. return;
  1087. }
  1088. KSTATUS
  1089. DwepCheckLink (
  1090. PDWE_DEVICE Device
  1091. )
  1092. /*++
  1093. Routine Description:
  1094. This routine checks to see if the media is connected and at what speed.
  1095. Arguments:
  1096. Device - Supplies a pointer to the device.
  1097. Return Value:
  1098. Status code.
  1099. --*/
  1100. {
  1101. BOOL FullDuplex;
  1102. BOOL LinkUp;
  1103. ULONGLONG Speed;
  1104. KSTATUS Status;
  1105. ULONG Value;
  1106. Status = DwepDetermineLinkParameters(Device, &LinkUp, &Speed, &FullDuplex);
  1107. if (!KSUCCESS(Status)) {
  1108. return Status;
  1109. }
  1110. if ((Device->LinkActive != LinkUp) ||
  1111. (Device->LinkSpeed != Speed) ||
  1112. (Device->FullDuplex != FullDuplex)) {
  1113. Value = DWE_READ(Device, DweRegisterMacConfiguration);
  1114. if (Speed == NET_SPEED_1000_MBPS) {
  1115. Value &= ~(DWE_MAC_CONFIGURATION_RMII_SPEED_100 |
  1116. DWE_MAC_CONFIGURATION_RMII_NOT_GIGABIT);
  1117. } else if (Speed == NET_SPEED_100_MBPS) {
  1118. Value |= DWE_MAC_CONFIGURATION_RMII_SPEED_100 |
  1119. DWE_MAC_CONFIGURATION_RMII_NOT_GIGABIT;
  1120. } else if (Speed == NET_SPEED_10_MBPS) {
  1121. Value &= ~DWE_MAC_CONFIGURATION_RMII_SPEED_100;
  1122. Value |= DWE_MAC_CONFIGURATION_RMII_NOT_GIGABIT;
  1123. }
  1124. Value &= ~DWE_MAC_CONFIGURATION_DUPLEX_MODE;
  1125. if (FullDuplex != FALSE) {
  1126. Value |= DWE_MAC_CONFIGURATION_DUPLEX_MODE;
  1127. }
  1128. DWE_WRITE(Device, DweRegisterMacConfiguration, Value);
  1129. Device->LinkActive = LinkUp;
  1130. Device->LinkSpeed = Speed;
  1131. Device->FullDuplex = FullDuplex;
  1132. NetSetLinkState(Device->NetworkLink, LinkUp, Speed);
  1133. }
  1134. return STATUS_SUCCESS;
  1135. }
  1136. KSTATUS
  1137. DwepDetermineLinkParameters (
  1138. PDWE_DEVICE Device,
  1139. PBOOL LinkUp,
  1140. PULONGLONG Speed,
  1141. PBOOL FullDuplex
  1142. )
  1143. /*++
  1144. Routine Description:
  1145. This routine reads the link parameters out of the PHY.
  1146. Arguments:
  1147. Device - Supplies a pointer to the device.
  1148. LinkUp - Supplies a pointer where a boolean will be returned indicating if
  1149. the media is connected or not.
  1150. Speed - Supplies a pointer where the link speed will be returned if
  1151. connected.
  1152. FullDuplex - Supplies a pointer where a boolean will be returned indicating
  1153. if the connection is full duplex (TRUE) or half duplex (FALSE).
  1154. Return Value:
  1155. Status code.
  1156. --*/
  1157. {
  1158. ULONG BasicControl;
  1159. ULONG BasicStatus;
  1160. ULONG BasicStatus2;
  1161. ULONG CommonLink;
  1162. ULONG GigabitControl;
  1163. ULONG GigabitStatus;
  1164. BOOL HasGigabit;
  1165. ULONG PartnerAbility;
  1166. KSTATUS Status;
  1167. *LinkUp = FALSE;
  1168. *Speed = NET_SPEED_NONE;
  1169. *FullDuplex = FALSE;
  1170. HasGigabit = FALSE;
  1171. Status = DwepReadMii(Device,
  1172. Device->PhyId,
  1173. MiiRegisterBasicStatus,
  1174. &BasicStatus);
  1175. if (!KSUCCESS(Status)) {
  1176. goto DetermineLinkParametersEnd;
  1177. }
  1178. Status = DwepReadMii(Device,
  1179. Device->PhyId,
  1180. MiiRegisterBasicStatus,
  1181. &BasicStatus2);
  1182. if (!KSUCCESS(Status)) {
  1183. goto DetermineLinkParametersEnd;
  1184. }
  1185. BasicStatus |= BasicStatus2;
  1186. if ((BasicStatus & MII_BASIC_STATUS_LINK_STATUS) == 0) {
  1187. goto DetermineLinkParametersEnd;
  1188. }
  1189. Status = DwepReadMii(Device,
  1190. Device->PhyId,
  1191. MiiRegisterBasicControl,
  1192. &BasicControl);
  1193. if (!KSUCCESS(Status)) {
  1194. goto DetermineLinkParametersEnd;
  1195. }
  1196. if ((BasicControl & MII_BASIC_CONTROL_ISOLATE) != 0) {
  1197. goto DetermineLinkParametersEnd;
  1198. }
  1199. if ((BasicControl & MII_BASIC_CONTROL_LOOPBACK) != 0) {
  1200. RtlDebugPrint("MII Loopback enabled!\n");
  1201. }
  1202. //
  1203. // The link status bit is set, so media is connected. Determine what type.
  1204. //
  1205. *LinkUp = TRUE;
  1206. if ((BasicControl & MII_BASIC_CONTROL_ENABLE_AUTONEGOTIATION) != 0) {
  1207. if ((BasicStatus & MII_BASIC_STATUS_AUTONEGOTIATE_COMPLETE) == 0) {
  1208. *LinkUp = FALSE;
  1209. goto DetermineLinkParametersEnd;
  1210. }
  1211. //
  1212. // Take the common set of the advertised abilities and the partner's
  1213. // abilities.
  1214. //
  1215. Status = DwepReadMii(Device,
  1216. Device->PhyId,
  1217. MiiRegisterAdvertise,
  1218. &CommonLink);
  1219. if (!KSUCCESS(Status)) {
  1220. goto DetermineLinkParametersEnd;
  1221. }
  1222. Status = DwepReadMii(Device,
  1223. Device->PhyId,
  1224. MiiRegisterLinkPartnerAbility,
  1225. &PartnerAbility);
  1226. if (!KSUCCESS(Status)) {
  1227. goto DetermineLinkParametersEnd;
  1228. }
  1229. CommonLink &= PartnerAbility;
  1230. GigabitStatus = 0;
  1231. GigabitControl = 0;
  1232. if (HasGigabit != FALSE) {
  1233. Status = DwepReadMii(Device,
  1234. Device->PhyId,
  1235. MiiRegisterGigabitStatus,
  1236. &GigabitStatus);
  1237. if (!KSUCCESS(Status)) {
  1238. goto DetermineLinkParametersEnd;
  1239. }
  1240. Status = DwepReadMii(Device,
  1241. Device->PhyId,
  1242. MiiRegisterGigabitControl,
  1243. &GigabitControl);
  1244. if (!KSUCCESS(Status)) {
  1245. goto DetermineLinkParametersEnd;
  1246. }
  1247. }
  1248. if (((GigabitControl & MII_GIGABIT_CONTROL_ADVERTISE_1000_FULL) != 0) &&
  1249. ((GigabitStatus & MII_GIGABIT_STATUS_PARTNER_1000_FULL) != 0)) {
  1250. *Speed = NET_SPEED_1000_MBPS;
  1251. *FullDuplex = TRUE;
  1252. } else if (((GigabitControl &
  1253. MII_GIGABIT_CONTROL_ADVERTISE_1000_HALF) != 0) &&
  1254. ((GigabitStatus &
  1255. MII_GIGABIT_STATUS_PARTNER_1000_HALF) != 0)) {
  1256. *Speed = NET_SPEED_1000_MBPS;
  1257. *FullDuplex = TRUE;
  1258. } else if ((CommonLink & MII_ADVERTISE_100_FULL) != 0) {
  1259. *Speed = NET_SPEED_100_MBPS;
  1260. *FullDuplex = TRUE;
  1261. } else if ((CommonLink & MII_ADVERTISE_100_BASE4) != 0) {
  1262. *Speed = NET_SPEED_100_MBPS;
  1263. *FullDuplex = TRUE;
  1264. } else if ((CommonLink & MII_ADVERTISE_100_HALF) != 0) {
  1265. *Speed = NET_SPEED_100_MBPS;
  1266. *FullDuplex = FALSE;
  1267. } else if ((CommonLink & MII_ADVERTISE_10_FULL) != 0) {
  1268. *Speed = NET_SPEED_10_MBPS;
  1269. *FullDuplex = TRUE;
  1270. } else if ((CommonLink & MII_ADVERTISE_10_HALF) != 0) {
  1271. *Speed = NET_SPEED_10_MBPS;
  1272. *FullDuplex = FALSE;
  1273. } else {
  1274. *LinkUp = FALSE;
  1275. }
  1276. }
  1277. DetermineLinkParametersEnd:
  1278. return Status;
  1279. }
  1280. KSTATUS
  1281. DwepReadMii (
  1282. PDWE_DEVICE Device,
  1283. ULONG Phy,
  1284. ULONG Register,
  1285. PULONG Result
  1286. )
  1287. /*++
  1288. Routine Description:
  1289. This routine reads a register from the PHY.
  1290. Arguments:
  1291. Device - Supplies a pointer to the device.
  1292. Phy - Supplies the address of the PHY.
  1293. Register - Supplies the register to read.
  1294. Result - Supplies a pointer where the result will be returned on success.
  1295. Return Value:
  1296. STATUS_SUCCESS on success.
  1297. STATUS_DEVICE_IO_ERROR if the device could not be read.
  1298. --*/
  1299. {
  1300. USHORT Mii;
  1301. ULONGLONG Timeout;
  1302. Mii = ((Phy & DWE_GMII_ADDRESS_DEVICE_MASK) <<
  1303. DWE_GMII_ADDRESS_DEVICE_SHIFT) |
  1304. ((Register & DWE_GMII_ADDRESS_REGISTER_MASK) <<
  1305. DWE_GMII_ADDRESS_REGISTER_SHIFT) |
  1306. (DWE_MII_CLOCK_VALUE << DWE_GMII_ADDRESS_CLOCK_RANGE_SHIFT) |
  1307. DWE_GMII_ADDRESS_BUSY;
  1308. DWE_WRITE(Device, DweRegisterGmiiAddress, Mii);
  1309. Timeout = KeGetRecentTimeCounter() +
  1310. (HlQueryTimeCounterFrequency() * DWE_MII_TIMEOUT);
  1311. do {
  1312. Mii = DWE_READ(Device, DweRegisterGmiiAddress);
  1313. if ((Mii & DWE_GMII_ADDRESS_BUSY) == 0) {
  1314. break;
  1315. }
  1316. KeYield();
  1317. } while (KeGetRecentTimeCounter() <= Timeout);
  1318. if ((Mii & DWE_GMII_ADDRESS_BUSY) != 0) {
  1319. return STATUS_DEVICE_IO_ERROR;
  1320. }
  1321. *Result = DWE_READ(Device, DweRegisterGmiiData);
  1322. return STATUS_SUCCESS;
  1323. }
  1324. KSTATUS
  1325. DwepWriteMii (
  1326. PDWE_DEVICE Device,
  1327. ULONG Phy,
  1328. ULONG Register,
  1329. ULONG Value
  1330. )
  1331. /*++
  1332. Routine Description:
  1333. This routine writes a register to the PHY.
  1334. Arguments:
  1335. Device - Supplies a pointer to the device.
  1336. Phy - Supplies the address of the PHY.
  1337. Register - Supplies the register to read.
  1338. Value - Supplies the value to write.
  1339. Return Value:
  1340. STATUS_SUCCESS on success.
  1341. STATUS_DEVICE_IO_ERROR if the operation timed out.
  1342. --*/
  1343. {
  1344. USHORT Mii;
  1345. ULONGLONG Timeout;
  1346. Mii = ((Phy & DWE_GMII_ADDRESS_DEVICE_MASK) <<
  1347. DWE_GMII_ADDRESS_DEVICE_SHIFT) |
  1348. ((Register & DWE_GMII_ADDRESS_REGISTER_MASK) <<
  1349. DWE_GMII_ADDRESS_REGISTER_SHIFT) |
  1350. (DWE_MII_CLOCK_VALUE << DWE_GMII_ADDRESS_CLOCK_RANGE_SHIFT) |
  1351. DWE_GMII_ADDRESS_WRITE | DWE_GMII_ADDRESS_BUSY;
  1352. DWE_WRITE(Device, DweRegisterGmiiData, Value);
  1353. DWE_WRITE(Device, DweRegisterGmiiAddress, Mii);
  1354. Timeout = KeGetRecentTimeCounter() +
  1355. (HlQueryTimeCounterFrequency() * DWE_MII_TIMEOUT);
  1356. do {
  1357. Mii = DWE_READ(Device, DweRegisterGmiiAddress);
  1358. if ((Mii & DWE_GMII_ADDRESS_BUSY) == 0) {
  1359. break;
  1360. }
  1361. KeYield();
  1362. } while (KeGetRecentTimeCounter() <= Timeout);
  1363. if ((Mii & DWE_GMII_ADDRESS_BUSY) != 0) {
  1364. return STATUS_DEVICE_IO_ERROR;
  1365. }
  1366. return STATUS_SUCCESS;
  1367. }