rtl81hw.c 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. rtl81hw.c
  5. Abstract:
  6. This module implements device support for the Realtek RTL81xx family of
  7. Ethernet controllers.
  8. Author:
  9. Chris Stevens 20-Jun-2014
  10. Environment:
  11. Kernel
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <minoca/kernel/driver.h>
  17. #include <minoca/net/netdrv.h>
  18. #include "rtl81.h"
  19. //
  20. // --------------------------------------------------------------------- Macros
  21. //
  22. //
  23. // These checksum macros can be used to determine if the IP, UDP, or TCP
  24. // checksum failure bits are set in a receive descriptors command value.
  25. //
  26. #define RTL81_RECEIVE_IP_CHECKSUM_FAILURE(_Command) \
  27. ((_Command & RTL81_RECEIVE_DESCRIPTOR_COMMAND_IP_CHECKSUM_FAILURE) != 0)
  28. #define RTL81_RECEIVE_UDP_CHECKSUM_FAILURE(_Command) \
  29. ((_Command & RTL81_RECEIVE_DESCRIPTOR_COMMAND_UDP_CHECKSUM_FAILURE) != 0)
  30. #define RTL81_RECEIVE_TCP_CHECKSUM_FAILURE(_Command) \
  31. ((_Command & RTL81_RECEIVE_DESCRIPTOR_COMMAND_TCP_CHECKSUM_FAILURE) != 0)
  32. //
  33. // ---------------------------------------------------------------- Definitions
  34. //
  35. //
  36. // Define the maximum number of pending packets that will be saved before the
  37. // driver starts to drop packets for legacy chips. Such chips only have 4
  38. // descriptors, but save a fair amount of packets to be sent.
  39. //
  40. #define RTL81_MAX_TRANSMIT_PACKET_LIST_COUNT_LEGACY 64
  41. //
  42. // ------------------------------------------------------ Data Type Definitions
  43. //
  44. //
  45. // ----------------------------------------------- Internal Function Prototypes
  46. //
  47. KSTATUS
  48. Rtl81pInitializePhy (
  49. PRTL81_DEVICE Device
  50. );
  51. VOID
  52. Rtl81pCheckLinkState (
  53. PRTL81_DEVICE Device
  54. );
  55. VOID
  56. Rtl81pReapTransmitDescriptors (
  57. PRTL81_DEVICE Device
  58. );
  59. VOID
  60. Rtl81pSendPendingPackets (
  61. PRTL81_DEVICE Device
  62. );
  63. VOID
  64. Rtl81pSendPacketsLegacy (
  65. PRTL81_DEVICE Device
  66. );
  67. VOID
  68. Rtl81pSendPacketsDefault (
  69. PRTL81_DEVICE Device
  70. );
  71. VOID
  72. Rtl81pReapReceivedFrames (
  73. PRTL81_DEVICE Device
  74. );
  75. VOID
  76. Rtl81pReapReceivedFramesLegacy (
  77. PRTL81_DEVICE Device
  78. );
  79. VOID
  80. Rtl81pReapReceivedFramesDefault (
  81. PRTL81_DEVICE Device
  82. );
  83. KSTATUS
  84. Rtl81pReadMacAddress (
  85. PRTL81_DEVICE Device
  86. );
  87. KSTATUS
  88. Rtl81pReadMdio (
  89. PRTL81_DEVICE Device,
  90. RTL81_MII_REGISTER Register,
  91. PULONG Data
  92. );
  93. KSTATUS
  94. Rtl81pWriteMdio (
  95. PRTL81_DEVICE Device,
  96. RTL81_MII_REGISTER Register,
  97. ULONG Data
  98. );
  99. //
  100. // -------------------------------------------------------------------- Globals
  101. //
  102. BOOL Rtl81DisablePacketDropping = FALSE;
  103. //
  104. // ------------------------------------------------------------------ Functions
  105. //
  106. KSTATUS
  107. Rtl81Send (
  108. PVOID DeviceContext,
  109. PNET_PACKET_LIST PacketList
  110. )
  111. /*++
  112. Routine Description:
  113. This routine sends data through the network.
  114. Arguments:
  115. DeviceContext - Supplies a pointer to the device context associated with
  116. the link down which this data is to be sent.
  117. PacketList - Supplies a pointer to a list of network packets to send. Data
  118. in these packets may be modified by this routine, but must not be used
  119. once this routine returns.
  120. Return Value:
  121. STATUS_SUCCESS if all packets were sent.
  122. STATUS_RESOURCE_IN_USE if some or all of the packets were dropped due to
  123. the hardware being backed up with too many packets to send.
  124. Other failure codes indicate that none of the packets were sent.
  125. --*/
  126. {
  127. PRTL81_DEVICE Device;
  128. UINTN PacketListCount;
  129. KSTATUS Status;
  130. ASSERT(KeGetRunLevel() == RunLevelLow);
  131. Device = (PRTL81_DEVICE)DeviceContext;
  132. KeAcquireQueuedLock(Device->TransmitLock);
  133. //
  134. // If there is any room in the packet list (or dropping packets is
  135. // disabled), add all of the packets to the list waiting to be sent.
  136. //
  137. PacketListCount = Device->TransmitPacketList.Count;
  138. if ((PacketListCount < Device->MaxTransmitPacketListCount) ||
  139. (Rtl81DisablePacketDropping != FALSE)) {
  140. NET_APPEND_PACKET_LIST(PacketList, &(Device->TransmitPacketList));
  141. Rtl81pSendPendingPackets(Device);
  142. Status = STATUS_SUCCESS;
  143. //
  144. // Otherwise report that the resource is use as it is too busy to handle
  145. // more packets.
  146. //
  147. } else {
  148. Status = STATUS_RESOURCE_IN_USE;
  149. }
  150. KeReleaseQueuedLock(Device->TransmitLock);
  151. return Status;
  152. }
  153. KSTATUS
  154. Rtl81GetSetInformation (
  155. PVOID DeviceContext,
  156. NET_LINK_INFORMATION_TYPE InformationType,
  157. PVOID Data,
  158. PUINTN DataSize,
  159. BOOL Set
  160. )
  161. /*++
  162. Routine Description:
  163. This routine gets or sets the network device layer's link information.
  164. Arguments:
  165. DeviceContext - Supplies a pointer to the device context associated with
  166. the link for which information is being set or queried.
  167. InformationType - Supplies the type of information being queried or set.
  168. Data - Supplies a pointer to the data buffer where the data is either
  169. returned for a get operation or given for a set operation.
  170. DataSize - Supplies a pointer that on input contains the size of the data
  171. buffer. On output, contains the required size of the data buffer.
  172. Set - Supplies a boolean indicating if this is a get operation (FALSE) or a
  173. set operation (TRUE).
  174. Return Value:
  175. Status code.
  176. --*/
  177. {
  178. ULONG ChangedFlags;
  179. PRTL81_DEVICE Device;
  180. PULONG Flags;
  181. KSTATUS Status;
  182. USHORT Value;
  183. Device = (PRTL81_DEVICE)DeviceContext;
  184. switch (InformationType) {
  185. case NetLinkInformationChecksumOffload:
  186. if (*DataSize != sizeof(ULONG)) {
  187. Status = STATUS_INVALID_PARAMETER;
  188. break;
  189. }
  190. //
  191. // If the request is a get, just return the device's current checksum
  192. // flags.
  193. //
  194. Status = STATUS_SUCCESS;
  195. Flags = (PULONG)Data;
  196. if (Set == FALSE) {
  197. *Flags = Device->ChecksumFlags;
  198. break;
  199. }
  200. //
  201. // Synchronize on the receive lock. There is nothing to do for transmit
  202. // changes, so leave that lock out of it.
  203. //
  204. KeAcquireQueuedLock(Device->ReceiveLock);
  205. //
  206. // If it is a set, figure out what is changing. There is nothing to do
  207. // if the change is in the transmit flags. Netcore requests transmit
  208. // offloads on a per-packet basis and there is not a global shut off on
  209. // RTL81xx devices. Requests to enable or disable receive checksum
  210. // offloading, however, need to modify the command 2 register.
  211. //
  212. ChangedFlags = *Flags ^ Device->ChecksumFlags;
  213. if ((ChangedFlags & NET_LINK_CHECKSUM_FLAG_RECEIVE_MASK) != 0) {
  214. //
  215. // If any of the receive checksum flags are set, then
  216. // offloading must remain on for all protocols. There is no
  217. // granularity. Turn it on if a flag is set and no flags were
  218. // previously set.
  219. //
  220. if (((*Flags & NET_LINK_CHECKSUM_FLAG_RECEIVE_MASK) != 0) &&
  221. ((Device->ChecksumFlags &
  222. NET_LINK_CHECKSUM_FLAG_RECEIVE_MASK) == 0)) {
  223. Value = RTL81_READ_REGISTER16(Device, Rtl81RegisterCommand2);
  224. Value |= RTL81_COMMAND_2_REGISTER_DEFAULT;
  225. RTL81_WRITE_REGISTER16(Device, Rtl81RegisterCommand2, Value);
  226. *Flags |= NET_LINK_CHECKSUM_FLAG_RECEIVE_MASK;
  227. //
  228. // Otherwise, if all flags are off and something was previously
  229. // set, turn receive checksum offloadng off.
  230. //
  231. } else if (((*Flags & NET_LINK_CHECKSUM_FLAG_RECEIVE_MASK) == 0) &&
  232. ((Device->ChecksumFlags &
  233. NET_LINK_CHECKSUM_FLAG_RECEIVE_MASK) != 0)) {
  234. Value = RTL81_READ_REGISTER16(Device, Rtl81RegisterCommand2);
  235. Value &= ~RTL81_COMMAND_2_REGISTER_DEFAULT;
  236. RTL81_WRITE_REGISTER16(Device, Rtl81RegisterCommand2, Value);
  237. }
  238. }
  239. //
  240. // Update the checksum flags.
  241. //
  242. Device->ChecksumFlags = *Flags;
  243. KeReleaseQueuedLock(Device->ReceiveLock);
  244. break;
  245. default:
  246. Status = STATUS_NOT_SUPPORTED;
  247. break;
  248. }
  249. return Status;
  250. }
  251. KSTATUS
  252. Rtl81pInitializeDeviceStructures (
  253. PRTL81_DEVICE Device
  254. )
  255. /*++
  256. Routine Description:
  257. This routine performs housekeeping preparation for resetting and enabling
  258. an RTL81xx device.
  259. Arguments:
  260. Device - Supplies a pointer to the device.
  261. Return Value:
  262. Status code.
  263. --*/
  264. {
  265. UINTN AllocationSize;
  266. PRTL81_DEFAULT_DATA DefaultData;
  267. PRTL81_RECEIVE_DESCRIPTOR Descriptor;
  268. ULONG Flags;
  269. ULONG Index;
  270. PIO_BUFFER IoBuffer;
  271. ULONG IoBufferFlags;
  272. PHYSICAL_ADDRESS PhysicalAddress;
  273. ULONGLONG Size;
  274. KSTATUS Status;
  275. ULONG Version;
  276. ASSERT(Device->TransmitLock == NULL);
  277. Device->TransmitLock = KeCreateQueuedLock();
  278. if (Device->TransmitLock == NULL) {
  279. Status = STATUS_INSUFFICIENT_RESOURCES;
  280. goto InitializeDeviceStructuresEnd;
  281. }
  282. ASSERT(Device->ReceiveLock == NULL);
  283. Device->ReceiveLock = KeCreateQueuedLock();
  284. if (Device->ReceiveLock == NULL) {
  285. Status = STATUS_INSUFFICIENT_RESOURCES;
  286. goto InitializeDeviceStructuresEnd;
  287. }
  288. NET_INITIALIZE_PACKET_LIST(&(Device->TransmitPacketList));
  289. //
  290. // The range of different RTL81xx devices use various register sets and
  291. // descriptor modes, among other scattered properties. Determine the card
  292. // type now and initialize the flags.
  293. //
  294. Flags = 0;
  295. Version = RTL81_READ_REGISTER32(Device, Rtl81RegisterTransmitConfiguration);
  296. Version &= RTL81_TRANSMIT_CONFIGURATION_HARDWARE_VERSION_MASK;
  297. switch (Version) {
  298. case RTL81_HARDWARE_VERSION_8101:
  299. case RTL81_HARDWARE_VERSION_8130:
  300. case RTL81_HARDWARE_VERSION_8139:
  301. case RTL81_HARDWARE_VERSION_8139A:
  302. case RTL81_HARDWARE_VERSION_8139AG:
  303. case RTL81_HARDWARE_VERSION_8139B:
  304. case RTL81_HARDWARE_VERSION_8139C:
  305. Flags = RTL81_FLAG_TRANSMIT_MODE_LEGACY |
  306. RTL81_FLAG_REGISTER_SET_LEGACY;
  307. break;
  308. case RTL81_HARDWARE_VERSION_8139CPLUS:
  309. Flags = RTL81_FLAG_REGISTER_SET_LEGACY |
  310. RTL81_FLAG_RECEIVE_COMMAND_LEGACY |
  311. RTL81_FLAG_DESCRIPTOR_LIMIT_64 |
  312. RTL81_FLAG_MULTI_SEGMENT_SUPPORT |
  313. RTL81_FLAG_CHECKSUM_OFFLOAD_DEFAULT;
  314. break;
  315. case RTL81_HARDWARE_VERSION_8102EL:
  316. case RTL81_HARDWARE_VERSION_8168E_VL:
  317. Flags = RTL81_FLAG_CHECKSUM_OFFLOAD_VLAN;
  318. break;
  319. default:
  320. RtlDebugPrint("RTL81: Untested hardware version 0x%08x.\n", Version);
  321. break;
  322. }
  323. Device->Flags = Flags;
  324. //
  325. // Both checksum versions support the same features. So start with checksum
  326. // offloading enabled for transmit and receive.
  327. //
  328. if ((Device->Flags & RTL81_FLAG_CHECKSUM_OFFLOAD_MASK) != 0) {
  329. Device->ChecksumFlags = NET_LINK_CHECKSUM_FLAG_TRANSMIT_IP_OFFLOAD |
  330. NET_LINK_CHECKSUM_FLAG_RECEIVE_IP_OFFLOAD |
  331. NET_LINK_CHECKSUM_FLAG_TRANSMIT_UDP_OFFLOAD |
  332. NET_LINK_CHECKSUM_FLAG_RECEIVE_UDP_OFFLOAD |
  333. NET_LINK_CHECKSUM_FLAG_TRANSMIT_TCP_OFFLOAD |
  334. NET_LINK_CHECKSUM_FLAG_RECEIVE_TCP_OFFLOAD;
  335. }
  336. //
  337. // Set up the common transmit and receive interrupt status bits.
  338. //
  339. Device->TransmitInterruptMask = RTL81_INTERRUPT_TRANSMIT_OK |
  340. RTL81_INTERRUPT_TRANSMIT_ERROR;
  341. Device->ReceiveInterruptMask = RTL81_INTERRUPT_RECEIVE_OK |
  342. RTL81_INTERRUPT_RECEIVE_ERROR;
  343. //
  344. // The legacy devices have different transmit and receive data
  345. // requirements, so separate the initialization structures based on the
  346. // flags.
  347. //
  348. if ((Flags & RTL81_FLAG_TRANSMIT_MODE_LEGACY) != 0) {
  349. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS;
  350. IoBuffer = MmAllocateNonPagedIoBuffer(
  351. 0,
  352. MAX_ULONG,
  353. RTL81_RECEIVE_RING_BUFFER_ALIGNMENT,
  354. RTL81_RECEIVE_RING_BUFFER_PADDED_SIZE,
  355. IoBufferFlags);
  356. if (IoBuffer == NULL) {
  357. Status = STATUS_INSUFFICIENT_RESOURCES;
  358. goto InitializeDeviceStructuresEnd;
  359. }
  360. ASSERT(IoBuffer->FragmentCount == 1);
  361. ASSERT(Device->U.LegacyData.ReceiveIoBuffer == NULL);
  362. Device->U.LegacyData.ReceiveIoBuffer = IoBuffer;
  363. ASSERT(Device->U.LegacyData.TransmitNextToUse == 0);
  364. ASSERT(Device->U.LegacyData.TransmitNextToClean == 0);
  365. Device->MaxTransmitPacketListCount =
  366. RTL81_MAX_TRANSMIT_PACKET_LIST_COUNT_LEGACY;
  367. } else {
  368. DefaultData = &(Device->U.DefaultData);
  369. if ((Flags & RTL81_FLAG_DESCRIPTOR_LIMIT_64) != 0) {
  370. DefaultData->TransmitDescriptorCount =
  371. RTL81_TRANSMIT_DESCRIPTOR_COUNT_LIMITED;
  372. DefaultData->ReceiveDescriptorCount =
  373. RTL81_RECEIVE_DESCRIPTOR_COUNT_LIMITED;
  374. } else {
  375. DefaultData->TransmitDescriptorCount =
  376. RTL81_TRANSMIT_DESCRIPTOR_COUNT_DEFAULT;
  377. DefaultData->ReceiveDescriptorCount =
  378. RTL81_RECEIVE_DESCRIPTOR_COUNT_DEFAULT;
  379. }
  380. Device->MaxTransmitPacketListCount =
  381. DefaultData->TransmitDescriptorCount * 2;
  382. AllocationSize = (DefaultData->TransmitDescriptorCount *
  383. sizeof(RTL81_TRANSMIT_DESCRIPTOR)) +
  384. (DefaultData->TransmitDescriptorCount *
  385. sizeof(PNET_PACKET_BUFFER)) +
  386. (DefaultData->ReceiveDescriptorCount *
  387. sizeof(RTL81_RECEIVE_DESCRIPTOR)) +
  388. (DefaultData->ReceiveDescriptorCount *
  389. RTL81_RECEIVE_BUFFER_DATA_SIZE);
  390. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS;
  391. IoBuffer = MmAllocateNonPagedIoBuffer(0,
  392. MAX_ULONGLONG,
  393. RTL81_DESCRIPTOR_ALIGNMENT,
  394. AllocationSize,
  395. IoBufferFlags);
  396. if (IoBuffer == NULL) {
  397. Status = STATUS_INSUFFICIENT_RESOURCES;
  398. goto InitializeDeviceStructuresEnd;
  399. }
  400. ASSERT(IoBuffer->FragmentCount == 1);
  401. //
  402. // Zero out everything except the receive packet data buffers.
  403. //
  404. Size = AllocationSize -
  405. (DefaultData->ReceiveDescriptorCount *
  406. RTL81_RECEIVE_BUFFER_DATA_SIZE);
  407. RtlZeroMemory(IoBuffer->Fragment[0].VirtualAddress, Size);
  408. //
  409. // Carve up the buffer, giving each array its piece.
  410. //
  411. PhysicalAddress = IoBuffer->Fragment[0].PhysicalAddress;
  412. DefaultData->TransmitDescriptor = IoBuffer->Fragment[0].VirtualAddress;
  413. ASSERT(IS_ALIGNED(PhysicalAddress, RTL81_DESCRIPTOR_ALIGNMENT));
  414. PhysicalAddress += (DefaultData->TransmitDescriptorCount *
  415. sizeof(RTL81_TRANSMIT_DESCRIPTOR));
  416. DefaultData->TransmitBuffer =
  417. (PNET_PACKET_BUFFER *)(DefaultData->TransmitDescriptor +
  418. DefaultData->TransmitDescriptorCount);
  419. PhysicalAddress += (DefaultData->TransmitDescriptorCount *
  420. sizeof(PNET_PACKET_BUFFER));
  421. DefaultData->ReceiveDescriptor =
  422. (PRTL81_RECEIVE_DESCRIPTOR)(DefaultData->TransmitBuffer +
  423. DefaultData->TransmitDescriptorCount);
  424. ASSERT(IS_ALIGNED(PhysicalAddress, RTL81_DESCRIPTOR_ALIGNMENT));
  425. PhysicalAddress += (DefaultData->ReceiveDescriptorCount *
  426. sizeof(RTL81_RECEIVE_DESCRIPTOR));
  427. DefaultData->ReceivePacketData =
  428. (PVOID)(DefaultData->ReceiveDescriptor +
  429. DefaultData->ReceiveDescriptorCount);
  430. ASSERT(Device->U.DefaultData.DescriptorIoBuffer == NULL);
  431. DefaultData->DescriptorIoBuffer = IoBuffer;
  432. ASSERT(DefaultData->TransmitNextToUse == 0);
  433. ASSERT(DefaultData->TransmitNextToClean == 0);
  434. ASSERT(DefaultData->ReceiveNextToReap == 0);
  435. //
  436. // Initialize the receive descriptors so that they are marked as owned
  437. // by the hardware and have the correct physical address and size in
  438. // place.
  439. //
  440. ASSERT(RTL81_RECEIVE_BUFFER_DATA_SIZE <=
  441. (RTL81_RECEIVE_DESCRIPTOR_COMMAND_SIZE_MASK >>
  442. RTL81_RECEIVE_DESCRIPTOR_COMMAND_SIZE_SHIFT));
  443. Descriptor = NULL;
  444. for (Index = 0;
  445. Index < DefaultData->ReceiveDescriptorCount;
  446. Index += 1) {
  447. Descriptor = &(DefaultData->ReceiveDescriptor[Index]);
  448. Descriptor->Command = RTL81_RECEIVE_DESCRIPTOR_DEFAULT_COMMAND;
  449. Descriptor->PhysicalAddress = PhysicalAddress;
  450. PhysicalAddress += RTL81_RECEIVE_BUFFER_DATA_SIZE;
  451. }
  452. //
  453. // Mark the last descriptor so that the hardware knows this is the end.
  454. //
  455. Descriptor->Command |= RTL81_RECEIVE_DESCRIPTOR_COMMAND_END_OF_RING;
  456. //
  457. // Add device specific transmit and receive mask bits.
  458. //
  459. Device->TransmitInterruptMask |= RTL81_INTERRUPT_TRANSMIT_UNAVAILABLE;
  460. Device->ReceiveInterruptMask |= RTL81_INTERRUPT_RECEIVE_OVERFLOW;
  461. }
  462. Status = STATUS_SUCCESS;
  463. InitializeDeviceStructuresEnd:
  464. return Status;
  465. }
  466. VOID
  467. Rtl81pDestroyDeviceStructures (
  468. PRTL81_DEVICE Device
  469. )
  470. /*++
  471. Routine Description:
  472. This routine performs destroy any device structures allocated for the
  473. RTL81xx device.
  474. Arguments:
  475. Device - Supplies a pointer to the device.
  476. Return Value:
  477. None.
  478. --*/
  479. {
  480. if (Device->TransmitLock != NULL) {
  481. KeDestroyQueuedLock(Device->TransmitLock);
  482. }
  483. if (Device->ReceiveLock != NULL) {
  484. KeDestroyQueuedLock(Device->ReceiveLock);
  485. }
  486. if ((Device->Flags & RTL81_FLAG_TRANSMIT_MODE_LEGACY) != 0) {
  487. if (Device->U.LegacyData.ReceiveIoBuffer != NULL) {
  488. MmFreeIoBuffer(Device->U.LegacyData.ReceiveIoBuffer);
  489. }
  490. } else {
  491. if (Device->U.DefaultData.DescriptorIoBuffer != NULL) {
  492. MmFreeIoBuffer(Device->U.DefaultData.DescriptorIoBuffer);
  493. }
  494. }
  495. return;
  496. }
  497. KSTATUS
  498. Rtl81pInitialize (
  499. PRTL81_DEVICE Device
  500. )
  501. /*++
  502. Routine Description:
  503. This routine initializes and enables the RTL81xx device.
  504. Arguments:
  505. Device - Supplies a pointer to the device.
  506. Return Value:
  507. Status code.
  508. --*/
  509. {
  510. USHORT Command2;
  511. BYTE CommandRegister;
  512. BYTE CommandRegisterMask;
  513. ULONGLONG CurrentTime;
  514. PIO_BUFFER_FRAGMENT Fragment;
  515. PHYSICAL_ADDRESS PhysicalAddress;
  516. ULONG ReceiveBufferStart;
  517. ULONG ReceiveConfiguration;
  518. KSTATUS Status;
  519. ULONGLONG Timeout;
  520. ULONGLONG TimeoutTicks;
  521. TimeoutTicks = HlQueryTimeCounterFrequency() * RTL81_DEVICE_TIMEOUT;
  522. //
  523. // Execute a software reset on the devices.
  524. //
  525. RTL81_WRITE_REGISTER8(Device,
  526. Rtl81RegisterCommand,
  527. RTL81_COMMAND_REGISTER_RESET);
  528. CurrentTime = KeGetRecentTimeCounter();
  529. Timeout = CurrentTime + TimeoutTicks;
  530. do {
  531. CommandRegister = RTL81_READ_REGISTER8(Device, Rtl81RegisterCommand);
  532. if ((CommandRegister & RTL81_COMMAND_REGISTER_RESET) == 0) {
  533. break;
  534. }
  535. CurrentTime = KeGetRecentTimeCounter();
  536. } while (CurrentTime <= Timeout);
  537. if (CurrentTime > Timeout) {
  538. Status = STATUS_TIMEOUT;
  539. goto InitializeEnd;
  540. }
  541. //
  542. // Get the MAC address out of the EEPROM.
  543. //
  544. Status = Rtl81pReadMacAddress(Device);
  545. if (!KSUCCESS(Status)) {
  546. goto InitializeEnd;
  547. }
  548. //
  549. // Reset the PHY and start auto-negotiation.
  550. //
  551. Status = Rtl81pInitializePhy(Device);
  552. if (!KSUCCESS(Status)) {
  553. goto InitializeEnd;
  554. }
  555. //
  556. // Disable all interrupts.
  557. //
  558. RTL81_WRITE_REGISTER16(Device, Rtl81RegisterInterruptMask, 0);
  559. //
  560. // Initialize the transmit and receive buffers based on the device type.
  561. //
  562. if ((Device->Flags & RTL81_FLAG_TRANSMIT_MODE_LEGACY) != 0) {
  563. Fragment = &(Device->U.LegacyData.ReceiveIoBuffer->Fragment[0]);
  564. ASSERT(Fragment->PhysicalAddress == (ULONG)Fragment->PhysicalAddress);
  565. ReceiveBufferStart = (ULONG)Fragment->PhysicalAddress;;
  566. RTL81_WRITE_REGISTER32(Device,
  567. Rtl81RegisterReceiveBufferStart,
  568. ReceiveBufferStart);
  569. } else {
  570. //
  571. // Enable transmit and receive in the second command register. Also
  572. // enable checksum offload on receive if set.
  573. //
  574. Command2 = RTL81_COMMAND_2_REGISTER_DEFAULT;
  575. if ((Device->ChecksumFlags &
  576. NET_LINK_CHECKSUM_FLAG_RECEIVE_MASK) != 0) {
  577. Command2 |= RTL81_COMMAND_2_REGISTER_RECEIVE_CHECKSUM_OFFLOAD;
  578. }
  579. RTL81_WRITE_REGISTER16(Device, Rtl81RegisterCommand2, Command2);
  580. Fragment = &(Device->U.DefaultData.DescriptorIoBuffer->Fragment[0]);
  581. PhysicalAddress = Fragment->PhysicalAddress;
  582. RTL81_WRITE_REGISTER32(Device,
  583. Rtl81RegisterTransmitDescriptorBaseLow,
  584. (ULONG)PhysicalAddress);
  585. RTL81_WRITE_REGISTER32(Device,
  586. Rtl81RegisterTransmitDescriptorBaseHigh,
  587. (ULONG)(PhysicalAddress >> 32));
  588. PhysicalAddress += (Device->U.DefaultData.TransmitDescriptorCount *
  589. sizeof(RTL81_TRANSMIT_DESCRIPTOR)) +
  590. (Device->U.DefaultData.TransmitDescriptorCount *
  591. sizeof(PNET_PACKET_BUFFER));
  592. RTL81_WRITE_REGISTER32(Device,
  593. Rtl81RegisterReceiveDescriptorBaseLow,
  594. (ULONG)PhysicalAddress);
  595. RTL81_WRITE_REGISTER32(Device,
  596. Rtl81RegisterReceiveDescriptorBaseHigh,
  597. (ULONG)(PhysicalAddress >> 32));
  598. }
  599. //
  600. // Enable transmit and receive.
  601. //
  602. CommandRegisterMask = RTL81_COMMAND_REGISTER_RECEIVE_ENABLE |
  603. RTL81_COMMAND_REGISTER_TRANSMIT_ENABLE;
  604. RTL81_WRITE_REGISTER8(Device, Rtl81RegisterCommand, CommandRegisterMask);
  605. CurrentTime = KeGetRecentTimeCounter();
  606. Timeout = CurrentTime + TimeoutTicks;
  607. do {
  608. CommandRegister = RTL81_READ_REGISTER8(Device, Rtl81RegisterCommand);
  609. if ((CommandRegister & CommandRegisterMask) == CommandRegisterMask) {
  610. break;
  611. }
  612. CurrentTime = KeGetRecentTimeCounter();
  613. } while (CurrentTime <= Timeout);
  614. if (CurrentTime > Timeout) {
  615. Status = STATUS_TIMEOUT;
  616. goto InitializeEnd;
  617. }
  618. //
  619. // Configure the transmit options. This must happen after transmit has been
  620. // enabled.
  621. //
  622. RTL81_WRITE_REGISTER32(Device,
  623. Rtl81RegisterTransmitConfiguration,
  624. RTL81_TRANSMIT_CONFIGURATION_DEFAULT_OPTIONS);
  625. //
  626. // Configure extra transmit registers for the devices using the newer
  627. // register set.
  628. //
  629. if ((Device->Flags & RTL81_FLAG_TRANSMIT_MODE_LEGACY) == 0) {
  630. RTL81_WRITE_REGISTER16(Device,
  631. Rtl81RegisterEarlyTransmitThreshold,
  632. RTL81_EARLY_TRANSMIT_THRESHOLD_DEFAULT);
  633. }
  634. //
  635. // Configure the receive options. This must happend after receive has been
  636. // enabled. Extra bits are needed for the RTL8139 chip.
  637. //
  638. ReceiveConfiguration = RTL81_RECEIVE_CONFIGURATION_DEFAULT_OPTIONS;
  639. if ((Device->Flags & RTL81_FLAG_TRANSMIT_MODE_LEGACY) != 0) {
  640. //
  641. // Note that the no-wrap bit has no effect when using a 64K buffer.
  642. //
  643. ReceiveConfiguration |=
  644. (RTL81_RECEIVE_CONFIGURATION_DEFAULT_EARLY_THRESHOLD <<
  645. RTL81_RECEIVE_CONFIGURATION_EARLY_TRESHOLD_SHIFT);
  646. }
  647. RTL81_WRITE_REGISTER32(Device,
  648. Rtl81RegisterReceiveConfiguration,
  649. ReceiveConfiguration);
  650. //
  651. // Configure extra receive registers for non RTL8139 devices.
  652. //
  653. if ((Device->Flags & RTL81_FLAG_REGISTER_SET_LEGACY) == 0) {
  654. RTL81_WRITE_REGISTER16(Device,
  655. Rtl81RegisterReceiveMaxPacketSize,
  656. RTL81_RECEIVE_BUFFER_DATA_SIZE);
  657. }
  658. //
  659. // Notify the networking core of this new link now that the device is ready
  660. // to send and receive data, pending media being present.
  661. //
  662. Status = Rtl81pAddNetworkDevice(Device);
  663. if (!KSUCCESS(Status)) {
  664. goto InitializeEnd;
  665. }
  666. //
  667. // Check to see if this link is up.
  668. //
  669. Rtl81pCheckLinkState(Device);
  670. //
  671. // Clear any pending interrupts and then enable the desired interrupts.
  672. //
  673. RTL81_WRITE_REGISTER16(Device,
  674. Rtl81RegisterInterruptStatus,
  675. RTL81_DEFAULT_INTERRUPT_MASK);
  676. RTL81_WRITE_REGISTER16(Device,
  677. Rtl81RegisterInterruptMask,
  678. RTL81_DEFAULT_INTERRUPT_MASK);
  679. Status = STATUS_SUCCESS;
  680. InitializeEnd:
  681. return Status;
  682. }
  683. INTERRUPT_STATUS
  684. Rtl81pInterruptService (
  685. PVOID Context
  686. )
  687. /*++
  688. Routine Description:
  689. This routine implements the RTL81xx interrupt service routine.
  690. Arguments:
  691. Context - Supplies the context pointer given to the system when the
  692. interrupt was connected. In this case, this points to the e100 device
  693. structure.
  694. Return Value:
  695. Interrupt status.
  696. --*/
  697. {
  698. PRTL81_DEVICE Device;
  699. USHORT PendingBits;
  700. Device = (PRTL81_DEVICE)Context;
  701. //
  702. // Read the status register, and if nothing is set then return immediately.
  703. //
  704. PendingBits = RTL81_READ_REGISTER16(Device, Rtl81RegisterInterruptStatus);
  705. PendingBits &= RTL81_DEFAULT_INTERRUPT_MASK;
  706. if (PendingBits == 0) {
  707. return InterruptStatusNotClaimed;
  708. }
  709. //
  710. // The RTL81xx devices that use MSIs require interrupts to be disabled and
  711. // enabled after each interrupt, otherwise the interrupts eventually stop
  712. // firing. That said, disable and enable the interrupts even if MSIs are
  713. // not in use.
  714. //
  715. RTL81_WRITE_REGISTER16(Device, Rtl81RegisterInterruptMask, 0);
  716. RTL81_WRITE_REGISTER16(Device, Rtl81RegisterInterruptStatus, PendingBits);
  717. RTL81_WRITE_REGISTER16(Device,
  718. Rtl81RegisterInterruptMask,
  719. RTL81_DEFAULT_INTERRUPT_MASK);
  720. RtlAtomicOr32(&(Device->PendingInterrupts), PendingBits);
  721. return InterruptStatusClaimed;
  722. }
  723. INTERRUPT_STATUS
  724. Rtl81pInterruptServiceWorker (
  725. PVOID Parameter
  726. )
  727. /*++
  728. Routine Description:
  729. This routine processes interrupts for the RTL81xx controller at low level.
  730. Arguments:
  731. Parameter - Supplies an optional parameter passed in by the creator of the
  732. work item.
  733. Return Value:
  734. Interrupt status.
  735. --*/
  736. {
  737. PRTL81_DEVICE Device;
  738. ULONG PendingBits;
  739. Device = (PRTL81_DEVICE)(Parameter);
  740. ASSERT(KeGetRunLevel() == RunLevelLow);
  741. //
  742. // Clear out the pending bits.
  743. //
  744. PendingBits = RtlAtomicExchange32(&(Device->PendingInterrupts), 0);
  745. if (PendingBits == 0) {
  746. return InterruptStatusNotClaimed;
  747. }
  748. //
  749. // Check to see if the link has changed.
  750. //
  751. if ((PendingBits & RTL81_INTERRUPT_LINK_CHANGE) != 0) {
  752. Rtl81pCheckLinkState(Device);
  753. }
  754. //
  755. // Communicate to the debugger if there were any receive errors.
  756. //
  757. if (((PendingBits & RTL81_INTERRUPT_RECEIVE_FIFO_OVERFLOW) != 0) ||
  758. ((PendingBits & RTL81_INTERRUPT_RECEIVE_ERROR) != 0) ||
  759. ((PendingBits & RTL81_INTERRUPT_RECEIVE_OVERFLOW) != 0)) {
  760. RtlDebugPrint("RTL81xx: Receive packet error 0x%x.\n", PendingBits);
  761. }
  762. //
  763. // If a packet was received, process it.
  764. //
  765. if ((PendingBits & Device->ReceiveInterruptMask) != 0) {
  766. Rtl81pReapReceivedFrames(Device);
  767. }
  768. //
  769. // If there was a transmit error or a successful transmit, then go through
  770. // and reap the packets.
  771. //
  772. if ((PendingBits & Device->TransmitInterruptMask) != 0) {
  773. Rtl81pReapTransmitDescriptors(Device);
  774. }
  775. return InterruptStatusClaimed;
  776. }
  777. //
  778. // --------------------------------------------------------- Internal Functions
  779. //
  780. KSTATUS
  781. Rtl81pInitializePhy (
  782. PRTL81_DEVICE Device
  783. )
  784. /*++
  785. Routine Description:
  786. This routine initializes the PHY on the RTL81xx.
  787. Arguments:
  788. Device - Supplies a pointer to the device.
  789. Return Value:
  790. Status code.
  791. --*/
  792. {
  793. USHORT BasicControl;
  794. ULONGLONG CurrentTime;
  795. KSTATUS Status;
  796. ULONGLONG Timeout;
  797. ULONGLONG TimeoutTicks;
  798. ULONG Value;
  799. TimeoutTicks = HlQueryTimeCounterFrequency() * RTL81_DEVICE_TIMEOUT;
  800. //
  801. // The RTL8139 based chips access the PHY through the basic mode registers.
  802. // Complete reset and auto-negotiation using those registers.
  803. //
  804. if ((Device->Flags & RTL81_FLAG_REGISTER_SET_LEGACY) != 0) {
  805. RTL81_WRITE_REGISTER16(Device,
  806. Rtl81RegisterBasicModeControl,
  807. RTL81_BASIC_MODE_CONTROL_INITIAL_VALUE);
  808. CurrentTime = KeGetRecentTimeCounter();
  809. Timeout = CurrentTime + TimeoutTicks;
  810. do {
  811. BasicControl = RTL81_READ_REGISTER16(Device,
  812. Rtl81RegisterBasicModeControl);
  813. if ((BasicControl & RTL81_BASIC_MODE_CONTROL_RESET) == 0) {
  814. break;
  815. }
  816. CurrentTime = KeGetRecentTimeCounter();
  817. } while (CurrentTime <= Timeout);
  818. if (CurrentTime > Timeout) {
  819. Status = STATUS_TIMEOUT;
  820. goto InitializePhyEnd;
  821. }
  822. //
  823. // RTL8168 and above access the PHY through the MII registers. Reset the
  824. // PHY and then start auto-negotiation.
  825. //
  826. } else {
  827. Status = Rtl81pWriteMdio(Device,
  828. Rtl81MiiRegisterBasicControl,
  829. RTL81_MII_BASIC_CONTROL_RESET);
  830. if (!KSUCCESS(Status)) {
  831. goto InitializePhyEnd;
  832. }
  833. CurrentTime = KeGetRecentTimeCounter();
  834. Timeout = CurrentTime + TimeoutTicks;
  835. do {
  836. Status = Rtl81pReadMdio(Device,
  837. Rtl81MiiRegisterBasicControl,
  838. &Value);
  839. if (!KSUCCESS(Status)) {
  840. goto InitializePhyEnd;
  841. }
  842. BasicControl = (USHORT)Value;
  843. if ((BasicControl & RTL81_MII_BASIC_CONTROL_RESET) == 0) {
  844. break;
  845. }
  846. CurrentTime = KeGetRecentTimeCounter();
  847. } while (CurrentTime <= Timeout);
  848. if (CurrentTime > Timeout) {
  849. Status = STATUS_TIMEOUT;
  850. goto InitializePhyEnd;
  851. }
  852. Status = Rtl81pWriteMdio(Device,
  853. Rtl81MiiRegisterAdvertise,
  854. RTL81_MII_ADVERTISE_ALL);
  855. if (!KSUCCESS(Status)) {
  856. goto InitializePhyEnd;
  857. }
  858. //
  859. // The gigabit control register needs to be read, modified, and
  860. // written as not all bits are advertisement related.
  861. //
  862. Status = Rtl81pReadMdio(Device, Rtl81MiiRegisterGigabitControl, &Value);
  863. if (!KSUCCESS(Status)) {
  864. goto InitializePhyEnd;
  865. }
  866. Value |= (RTL81_MII_GIGABIT_CONTROL_ADVERTISE_1000_FULL |
  867. RTL81_MII_GIGABIT_CONTROL_ADVERTISE_1000_HALF);
  868. Status = Rtl81pWriteMdio(Device, Rtl81MiiRegisterGigabitControl, Value);
  869. if (!KSUCCESS(Status)) {
  870. goto InitializePhyEnd;
  871. }
  872. Value = RTL81_MII_BASIC_CONTROL_ENABLE_AUTONEGOTIATION |
  873. RTL81_MII_BASIC_CONTROL_RESTART_AUTONEGOTIATION;
  874. Status = Rtl81pWriteMdio(Device, Rtl81MiiRegisterBasicControl, Value);
  875. if (!KSUCCESS(Status)) {
  876. goto InitializePhyEnd;
  877. }
  878. }
  879. Status = STATUS_SUCCESS;
  880. InitializePhyEnd:
  881. return Status;
  882. }
  883. VOID
  884. Rtl81pCheckLinkState (
  885. PRTL81_DEVICE Device
  886. )
  887. /*++
  888. Routine Description:
  889. This routine checks the state of the link and will notify the networking
  890. core if the link is up or down.
  891. Arguments:
  892. Device - Supplies a pointer to the RTL81xx device.
  893. Return Value:
  894. None.
  895. --*/
  896. {
  897. ULONGLONG LinkSpeed;
  898. BYTE MediaStatus;
  899. BYTE PhyStatus;
  900. //
  901. // The RTL8139 based devices use the media status register.
  902. //
  903. if ((Device->Flags & RTL81_FLAG_REGISTER_SET_LEGACY) != 0) {
  904. MediaStatus = RTL81_READ_REGISTER8(Device, Rtl81RegisterMediaStatus);
  905. if ((MediaStatus & RTL81_MEDIA_STATUS_SPEED_10) != 0) {
  906. LinkSpeed = NET_SPEED_10_MBPS;
  907. } else {
  908. LinkSpeed = NET_SPEED_100_MBPS;
  909. }
  910. if ((MediaStatus & RTL81_MEDIA_STATUS_LINK_DOWN) == 0) {
  911. NetSetLinkState(Device->NetworkLink, TRUE, LinkSpeed);
  912. } else {
  913. NetSetLinkState(Device->NetworkLink, FALSE, LinkSpeed);
  914. }
  915. //
  916. // Otherwise the PHY status register is used.
  917. //
  918. } else {
  919. PhyStatus = RTL81_READ_REGISTER8(Device, Rtl81RegisterPhyStatus);
  920. if ((PhyStatus & RTL81_PHY_STATUS_SPEED_10) != 0) {
  921. LinkSpeed = NET_SPEED_10_MBPS;
  922. } else if ((PhyStatus & RTL81_PHY_STATUS_SPEED_100) != 0) {
  923. LinkSpeed = NET_SPEED_100_MBPS;
  924. } else if ((PhyStatus & RTL81_PHY_STATUS_SPEED_1000) != 0) {
  925. LinkSpeed = NET_SPEED_1000_MBPS;
  926. } else {
  927. ASSERT((PhyStatus & RTL81_PHY_STATUS_LINK_UP) == 0);
  928. LinkSpeed = 0;
  929. }
  930. if ((PhyStatus & RTL81_PHY_STATUS_LINK_UP) != 0) {
  931. NetSetLinkState(Device->NetworkLink, TRUE, LinkSpeed);
  932. } else {
  933. NetSetLinkState(Device->NetworkLink, FALSE, LinkSpeed);
  934. }
  935. }
  936. return;
  937. }
  938. VOID
  939. Rtl81pReapTransmitDescriptors (
  940. PRTL81_DEVICE Device
  941. )
  942. /*++
  943. Routine Description:
  944. This routine attempts to reap any transmit descriptors that completed or
  945. experienced an error. It will send along more data if it released any
  946. descriptors.
  947. Arguments:
  948. Device - Supplies a pointer to the RTL81xx device.
  949. Return Value:
  950. None.
  951. --*/
  952. {
  953. ULONG Command;
  954. PRTL81_DEFAULT_DATA DefaultData;
  955. PRTL81_TRANSMIT_DESCRIPTOR Descriptor;
  956. BOOL DescriptorReaped;
  957. LIST_ENTRY DestroyList;
  958. PRTL81_LEGACY_DATA LegacyData;
  959. USHORT NextToClean;
  960. PNET_PACKET_BUFFER Packet;
  961. RTL81_REGISTER Register;
  962. ULONG TransmitStatus;
  963. DescriptorReaped = FALSE;
  964. INITIALIZE_LIST_HEAD(&DestroyList);
  965. KeAcquireQueuedLock(Device->TransmitLock);
  966. //
  967. // Check all descriptors between the next to clean and the next to use. If
  968. // the two values are equal and an interrupt came in, it likely means that
  969. // all descriptors are eligble for reaping, rather than none. Split this
  970. // logic based on the device type.
  971. //
  972. if ((Device->Flags & RTL81_FLAG_TRANSMIT_MODE_LEGACY) != 0) {
  973. LegacyData = &(Device->U.LegacyData);
  974. do {
  975. NextToClean = LegacyData->TransmitNextToClean;
  976. //
  977. // If the next descriptor to clean is not in use, then skip
  978. // cleaning entirely.
  979. //
  980. if (LegacyData->ActiveTransmitPackets[NextToClean] == NULL) {
  981. break;
  982. }
  983. Register = Rtl81RegisterTransmitStatus0 +
  984. (NextToClean * sizeof(ULONG));
  985. TransmitStatus = RTL81_READ_REGISTER32(Device, Register);
  986. //
  987. // If the transmission was not aborted, completed or underrun, then
  988. // the descriptor cannot be reaped. Break out of the loop as the
  989. // descriptors are serviced in round-robin style.
  990. //
  991. if (((TransmitStatus & RTL81_TRANSMIT_STATUS_ABORT) == 0) &&
  992. ((TransmitStatus & RTL81_TRANSMIT_STATUS_OK) == 0) &&
  993. ((TransmitStatus & RTL81_TRANSMIT_STATUS_FIFO_UNDERRUN) == 0)) {
  994. break;
  995. }
  996. DescriptorReaped = TRUE;
  997. Packet = LegacyData->ActiveTransmitPackets[NextToClean];
  998. INSERT_BEFORE(&(Packet->ListEntry), &DestroyList);
  999. LegacyData->ActiveTransmitPackets[NextToClean] = NULL;
  1000. //
  1001. // Advance to clean the next descriptor.
  1002. //
  1003. LegacyData->TransmitNextToClean += 1;
  1004. if (LegacyData->TransmitNextToClean ==
  1005. RTL81_TRANSMIT_DESCRIPTOR_COUNT_LEGACY) {
  1006. LegacyData->TransmitNextToClean = 0;
  1007. }
  1008. } while (LegacyData->TransmitNextToClean !=
  1009. LegacyData->TransmitNextToUse);
  1010. } else {
  1011. DefaultData = &(Device->U.DefaultData);
  1012. do {
  1013. NextToClean = DefaultData->TransmitNextToClean;
  1014. //
  1015. // If the next descriptor to clean is not in use, then skip
  1016. // cleaning entirely.
  1017. //
  1018. if (DefaultData->TransmitBuffer[NextToClean] == NULL) {
  1019. break;
  1020. }
  1021. Descriptor = &(DefaultData->TransmitDescriptor[NextToClean]);
  1022. Command = Descriptor->Command;
  1023. //
  1024. // If the hardware still owns the descriptor, then it cannot be
  1025. // reclaimed. Skip the rest of the cleaning.
  1026. //
  1027. if ((Command & RTL81_TRANSMIT_DESCRIPTOR_COMMAND_OWN) != 0) {
  1028. break;
  1029. }
  1030. DescriptorReaped = TRUE;
  1031. Packet = DefaultData->TransmitBuffer[NextToClean];
  1032. INSERT_BEFORE(&(Packet->ListEntry), &DestroyList);
  1033. DefaultData->TransmitBuffer[NextToClean] = NULL;
  1034. //
  1035. // Advance to clean the next descriptor.
  1036. //
  1037. DefaultData->TransmitNextToClean += 1;
  1038. if (DefaultData->TransmitNextToClean ==
  1039. DefaultData->TransmitDescriptorCount) {
  1040. DefaultData->TransmitNextToClean = 0;
  1041. }
  1042. } while (DefaultData->TransmitNextToClean !=
  1043. DefaultData->TransmitNextToUse);
  1044. //
  1045. // If there are still packets waiting to be sent, then flush them
  1046. // through in case the hardware went idle.
  1047. //
  1048. if (DefaultData->TransmitNextToClean !=
  1049. DefaultData->TransmitNextToUse) {
  1050. if ((Device->Flags & RTL81_FLAG_REGISTER_SET_LEGACY) != 0) {
  1051. RTL81_WRITE_REGISTER8(Device,
  1052. Rtl81RegisterTransmitPriorityPolling2,
  1053. RTL81_TRANSMIT_PRIORITY_POLLING_NORMAL);
  1054. } else {
  1055. RTL81_WRITE_REGISTER8(Device,
  1056. Rtl81RegisterTransmitPriorityPolling1,
  1057. RTL81_TRANSMIT_PRIORITY_POLLING_NORMAL);
  1058. }
  1059. }
  1060. }
  1061. //
  1062. // If a descriptor was reaped, then try to pump more packets through.
  1063. //
  1064. if (DescriptorReaped != FALSE) {
  1065. Rtl81pSendPendingPackets(Device);
  1066. }
  1067. KeReleaseQueuedLock(Device->TransmitLock);
  1068. //
  1069. // Destroy any reaped buffers.
  1070. //
  1071. while (LIST_EMPTY(&DestroyList) == FALSE) {
  1072. Packet = LIST_VALUE(DestroyList.Next, NET_PACKET_BUFFER, ListEntry);
  1073. LIST_REMOVE(&(Packet->ListEntry));
  1074. NetFreeBuffer(Packet);
  1075. }
  1076. return;
  1077. }
  1078. VOID
  1079. Rtl81pSendPendingPackets (
  1080. PRTL81_DEVICE Device
  1081. )
  1082. /*++
  1083. Routine Description:
  1084. This routine sends any pending packets as long as there are free
  1085. descriptors available. This routine assumes that the device's lock is held.
  1086. Arguments:
  1087. Device - Supplies a pointer to the RTL81xx device.
  1088. Return Value:
  1089. None.
  1090. --*/
  1091. {
  1092. if ((Device->Flags & RTL81_FLAG_TRANSMIT_MODE_LEGACY) != 0) {
  1093. Rtl81pSendPacketsLegacy(Device);
  1094. } else {
  1095. Rtl81pSendPacketsDefault(Device);
  1096. }
  1097. return;
  1098. }
  1099. VOID
  1100. Rtl81pSendPacketsLegacy (
  1101. PRTL81_DEVICE Device
  1102. )
  1103. /*++
  1104. Routine Description:
  1105. This routine sends any pending packets for a legacy transmit device as long
  1106. as there are free descriptors available. This routine assumes that the
  1107. device's lock is held.
  1108. Arguments:
  1109. Device - Supplies a pointer to the RTL81xx device.
  1110. Return Value:
  1111. None.
  1112. --*/
  1113. {
  1114. PRTL81_LEGACY_DATA LegacyData;
  1115. USHORT NextToUse;
  1116. ULONG Offset;
  1117. PNET_PACKET_BUFFER Packet;
  1118. PHYSICAL_ADDRESS PhysicalAddress;
  1119. ULONG Size;
  1120. ASSERT(KeIsQueuedLockHeld(Device->TransmitLock) != FALSE);
  1121. ASSERT((Device->Flags & RTL81_FLAG_TRANSMIT_MODE_LEGACY) != 0);
  1122. //
  1123. // Iterate over the list of pending transmit packets allocating them to
  1124. // free descriptors, if there are any.
  1125. //
  1126. LegacyData = &(Device->U.LegacyData);
  1127. while (NET_PACKET_LIST_EMPTY(&(Device->TransmitPacketList)) == FALSE) {
  1128. //
  1129. // Get the next descriptor to use. If it is not available, then
  1130. // exit. Otherwise increment the next to use index.
  1131. //
  1132. NextToUse = LegacyData->TransmitNextToUse;
  1133. if (LegacyData->ActiveTransmitPackets[NextToUse] != NULL) {
  1134. break;
  1135. }
  1136. LegacyData->TransmitNextToUse += 1;
  1137. if (LegacyData->TransmitNextToUse ==
  1138. RTL81_TRANSMIT_DESCRIPTOR_COUNT_LEGACY) {
  1139. LegacyData->TransmitNextToUse = 0;
  1140. }
  1141. Packet = LIST_VALUE(Device->TransmitPacketList.Head.Next,
  1142. NET_PACKET_BUFFER,
  1143. ListEntry);
  1144. NET_REMOVE_PACKET_FROM_LIST(Packet, &(Device->TransmitPacketList));
  1145. //
  1146. // Remember the packet so that it can be released once it is
  1147. // successfully sent and then begin the transmit process. Setting
  1148. // the size in the status register also sets the OWN bit to 0,
  1149. // triggering the start of the transmission. Thus, the physical
  1150. // address must be programmed first.
  1151. //
  1152. ASSERT(LegacyData->ActiveTransmitPackets[NextToUse] == NULL);
  1153. LegacyData->ActiveTransmitPackets[NextToUse] = Packet;
  1154. Offset = NextToUse * sizeof(ULONG);
  1155. PhysicalAddress = Packet->BufferPhysicalAddress + Packet->DataOffset;
  1156. ASSERT(PhysicalAddress == (ULONG)PhysicalAddress);
  1157. RTL81_WRITE_REGISTER32(Device,
  1158. (Rtl81RegisterTransmitAddress0 + Offset),
  1159. (ULONG)PhysicalAddress);
  1160. Size = Packet->FooterOffset - Packet->DataOffset;
  1161. ASSERT(Size <= RTL81_MAX_TRANSMIT_PACKET_SIZE);
  1162. //
  1163. // The RTL8139C does not automatically pad runt packets (less than
  1164. // 64 bytes). The buffer should have been zero'd as this driver
  1165. // registered a minimum packet length with net core. Adjust the size,
  1166. // leaving space for the hardware to fill in the CRC.
  1167. //
  1168. if (Size < (RTL81_MINIMUM_PACKET_LENGTH - sizeof(ULONG))) {
  1169. ASSERT(Packet->BufferSize >= RTL81_MINIMUM_PACKET_LENGTH);
  1170. Size = RTL81_MINIMUM_PACKET_LENGTH - sizeof(ULONG);
  1171. }
  1172. RTL81_WRITE_REGISTER32(Device,
  1173. (Rtl81RegisterTransmitStatus0 + Offset),
  1174. Size);
  1175. }
  1176. return;
  1177. }
  1178. VOID
  1179. Rtl81pSendPacketsDefault (
  1180. PRTL81_DEVICE Device
  1181. )
  1182. /*++
  1183. Routine Description:
  1184. This routine sends any pending packets for a default transmit device as
  1185. long as there are free descriptors available. This routine assumes that the
  1186. device's lock is held.
  1187. Arguments:
  1188. Device - Supplies a pointer to the RTL81xx device.
  1189. Return Value:
  1190. None.
  1191. --*/
  1192. {
  1193. ULONG Command;
  1194. PRTL81_DEFAULT_DATA DefaultData;
  1195. PRTL81_TRANSMIT_DESCRIPTOR Descriptor;
  1196. ULONG Flags;
  1197. USHORT NextToUse;
  1198. PNET_PACKET_BUFFER Packet;
  1199. BOOL PacketSubmitted;
  1200. PHYSICAL_ADDRESS PhysicalAddress;
  1201. ULONG Size;
  1202. ULONG VlanTag;
  1203. ASSERT(KeIsQueuedLockHeld(Device->TransmitLock) != FALSE);
  1204. ASSERT((Device->Flags & RTL81_FLAG_TRANSMIT_MODE_LEGACY) == 0);
  1205. //
  1206. // Iterate over the list of pending transmit packets allocating them to
  1207. // free descriptors, if there are any.
  1208. //
  1209. DefaultData = &(Device->U.DefaultData);
  1210. PacketSubmitted = FALSE;
  1211. while (NET_PACKET_LIST_EMPTY(&(Device->TransmitPacketList)) == FALSE) {
  1212. //
  1213. // Get the next descriptor to use. If it is not available, then
  1214. // exit. Otherwise increment the next to use index.
  1215. //
  1216. NextToUse = DefaultData->TransmitNextToUse;
  1217. if (DefaultData->TransmitBuffer[NextToUse] != NULL) {
  1218. break;
  1219. }
  1220. DefaultData->TransmitNextToUse += 1;
  1221. if (DefaultData->TransmitNextToUse ==
  1222. DefaultData->TransmitDescriptorCount) {
  1223. DefaultData->TransmitNextToUse = 0;
  1224. }
  1225. Packet = LIST_VALUE(Device->TransmitPacketList.Head.Next,
  1226. NET_PACKET_BUFFER,
  1227. ListEntry);
  1228. NET_REMOVE_PACKET_FROM_LIST(Packet, &(Device->TransmitPacketList));
  1229. //
  1230. // Remember the packet so that it can be released once it is
  1231. // successfully sent and then begin the transmit process.
  1232. //
  1233. ASSERT(DefaultData->TransmitBuffer[NextToUse] == NULL);
  1234. DefaultData->TransmitBuffer[NextToUse] = Packet;
  1235. //
  1236. // Program the descriptor with the packets data.
  1237. //
  1238. Size = Packet->FooterOffset - Packet->DataOffset;
  1239. ASSERT(Size <= RTL81_MAX_TRANSMIT_PACKET_SIZE);
  1240. Command = RTL81_TRANSMIT_DESCRIPTOR_COMMAND_OWN |
  1241. RTL81_TRANSMIT_DESCRIPTOR_COMMAND_FIRST_SEGMENT |
  1242. RTL81_TRANSMIT_DESCRIPTOR_COMMAND_LAST_SEGMENT |
  1243. ((Size << RTL81_TRANSMIT_DESCRIPTOR_COMMAND_SIZE_SHIFT) &
  1244. RTL81_TRANSMIT_DESCRIPTOR_COMMAND_SIZE_MASK);
  1245. //
  1246. // See if any checksum offloads were requested.
  1247. //
  1248. VlanTag = 0;
  1249. if ((Device->Flags & RTL81_FLAG_CHECKSUM_OFFLOAD_DEFAULT) != 0) {
  1250. Flags = Packet->Flags;
  1251. if ((Flags & NET_PACKET_FLAG_IP_CHECKSUM_OFFLOAD) != 0) {
  1252. Command |=
  1253. RTL81_TRANSMIT_DESCRIPTOR_COMMAND_IP_CHECKSUM_OFFLOAD;
  1254. }
  1255. if ((Flags & NET_PACKET_FLAG_UDP_CHECKSUM_OFFLOAD) != 0) {
  1256. Command |=
  1257. RTL81_TRANSMIT_DESCRIPTOR_COMMAND_UDP_CHECKSUM_OFFLOAD;
  1258. } else if ((Flags & NET_PACKET_FLAG_TCP_CHECKSUM_OFFLOAD) != 0) {
  1259. Command |=
  1260. RTL81_TRANSMIT_DESCRIPTOR_COMMAND_TCP_CHECKSUM_OFFLOAD;
  1261. }
  1262. } else if ((Device->Flags & RTL81_FLAG_CHECKSUM_OFFLOAD_VLAN) != 0) {
  1263. Flags = Packet->Flags;
  1264. if ((Flags & NET_PACKET_FLAG_IP_CHECKSUM_OFFLOAD) != 0) {
  1265. VlanTag |= RTL81_TRANSMIT_DESCRIPTOR_VLAN_IP_CHECKSUM_OFFLOAD;
  1266. }
  1267. if ((Flags & NET_PACKET_FLAG_UDP_CHECKSUM_OFFLOAD) != 0) {
  1268. VlanTag |= RTL81_TRANSMIT_DESCRIPTOR_VLAN_UDP_CHECKSUM_OFFLOAD;
  1269. } else if ((Flags & NET_PACKET_FLAG_TCP_CHECKSUM_OFFLOAD) != 0) {
  1270. VlanTag |= RTL81_TRANSMIT_DESCRIPTOR_VLAN_TCP_CHECKSUM_OFFLOAD;
  1271. }
  1272. }
  1273. if (NextToUse == (DefaultData->TransmitDescriptorCount - 1)) {
  1274. Command |= RTL81_TRANSMIT_DESCRIPTOR_COMMAND_END_OF_RING;
  1275. }
  1276. PhysicalAddress = Packet->BufferPhysicalAddress +
  1277. Packet->DataOffset;
  1278. Descriptor = &(DefaultData->TransmitDescriptor[NextToUse]);
  1279. Descriptor->VlanTag = VlanTag;
  1280. Descriptor->PhysicalAddress = PhysicalAddress;
  1281. RtlMemoryBarrier();
  1282. Descriptor->Command = Command;
  1283. PacketSubmitted = TRUE;
  1284. }
  1285. //
  1286. // If a packet was submitted by setting its state in a descriptor, then
  1287. // poke the hardware to let it know to check the transmit queue.
  1288. //
  1289. if (PacketSubmitted != FALSE) {
  1290. if ((Device->Flags & RTL81_FLAG_REGISTER_SET_LEGACY) != 0) {
  1291. RTL81_WRITE_REGISTER8(Device,
  1292. Rtl81RegisterTransmitPriorityPolling2,
  1293. RTL81_TRANSMIT_PRIORITY_POLLING_NORMAL);
  1294. } else {
  1295. RTL81_WRITE_REGISTER8(Device,
  1296. Rtl81RegisterTransmitPriorityPolling1,
  1297. RTL81_TRANSMIT_PRIORITY_POLLING_NORMAL);
  1298. }
  1299. }
  1300. return;
  1301. }
  1302. VOID
  1303. Rtl81pReapReceivedFrames (
  1304. PRTL81_DEVICE Device
  1305. )
  1306. /*++
  1307. Routine Description:
  1308. This routine reaps received frames from RTL81xx hardware and notifies the
  1309. core networking driver about a packet's arrival.
  1310. Arguments:
  1311. Device - Supplies a pointer to the RTL81xx device.
  1312. Return Value:
  1313. None.
  1314. --*/
  1315. {
  1316. KeAcquireQueuedLock(Device->ReceiveLock);
  1317. //
  1318. // Handle the reaping based on the device type. RTL8139 is different than
  1319. // everything else.
  1320. //
  1321. if ((Device->Flags & RTL81_FLAG_TRANSMIT_MODE_LEGACY) != 0) {
  1322. Rtl81pReapReceivedFramesLegacy(Device);
  1323. } else {
  1324. Rtl81pReapReceivedFramesDefault(Device);
  1325. }
  1326. KeReleaseQueuedLock(Device->ReceiveLock);
  1327. return;
  1328. }
  1329. VOID
  1330. Rtl81pReapReceivedFramesLegacy (
  1331. PRTL81_DEVICE Device
  1332. )
  1333. /*++
  1334. Routine Description:
  1335. This routine reaps received frames from the legacy RTL receive ring buffer
  1336. and notifies the core networking driver about a packet's arrival.
  1337. Arguments:
  1338. Device - Supplies a pointer to the RTL81xx device.
  1339. Return Value:
  1340. None.
  1341. --*/
  1342. {
  1343. USHORT AlignedOffset;
  1344. USHORT BytesReaped;
  1345. BYTE CommandRegister;
  1346. USHORT CurrentOffset;
  1347. BYTE EarlyStatus;
  1348. USHORT EndOffset;
  1349. PIO_BUFFER_FRAGMENT Fragment;
  1350. PRTL81_PACKET_HEADER Header;
  1351. PRTL81_LEGACY_DATA LegacyData;
  1352. USHORT MaxBytesToReap;
  1353. NET_PACKET_BUFFER Packet;
  1354. USHORT PacketLength;
  1355. PHYSICAL_ADDRESS PhysicalAddress;
  1356. USHORT ReadPacketAddress;
  1357. PVOID VirtualAddress;
  1358. USHORT WrapLength;
  1359. USHORT WrapOffset;
  1360. ASSERT((Device->Flags & RTL81_FLAG_TRANSMIT_MODE_LEGACY) != 0);
  1361. LegacyData = &(Device->U.LegacyData);
  1362. Packet.IoBuffer = NULL;
  1363. Packet.ListEntry.Next = NULL;
  1364. Packet.Flags = 0;
  1365. //
  1366. // Get the current read offset and the hardware's write offset.
  1367. //
  1368. CurrentOffset = RTL81_READ_REGISTER16(Device,
  1369. Rtl81RegisterReadPacketAddress);
  1370. CurrentOffset += RTL81_RECEIVE_OFFSET_ADJUSTMENT;
  1371. if (CurrentOffset >= RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET) {
  1372. CurrentOffset -= RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET;
  1373. }
  1374. EndOffset = RTL81_READ_REGISTER16(Device,
  1375. Rtl81RegisterReceiveBufferCurrent);
  1376. ASSERT(EndOffset < RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET);
  1377. //
  1378. // Figure how many good bytes are available to process, accounting for
  1379. // the wrap around.
  1380. //
  1381. if (EndOffset > CurrentOffset) {
  1382. MaxBytesToReap = EndOffset - CurrentOffset;
  1383. } else {
  1384. MaxBytesToReap = (RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET -
  1385. CurrentOffset) +
  1386. EndOffset;
  1387. }
  1388. Fragment = &(LegacyData->ReceiveIoBuffer->Fragment[0]);
  1389. VirtualAddress = Fragment->VirtualAddress;
  1390. PhysicalAddress = Fragment->PhysicalAddress;
  1391. //
  1392. // Loop until the buffer is empty according to the command register or
  1393. // until the maximum bytes have been reaped.
  1394. //
  1395. BytesReaped = 0;
  1396. CommandRegister = RTL81_READ_REGISTER8(Device, Rtl81RegisterCommand);
  1397. while ((CommandRegister & RTL81_COMMAND_REGISTER_BUFFER_EMPTY) == 0) {
  1398. Header = (PRTL81_PACKET_HEADER)(VirtualAddress + CurrentOffset);
  1399. //
  1400. // If the packet is early or there was an error, break out of the loop.
  1401. //
  1402. if (((Header->Status & RTL81_RECEIVE_PACKET_STATUS_OK) == 0) ||
  1403. ((Header->Status & RTL81_RECEIVE_PACKET_ERROR_MASK) != 0) ||
  1404. (Header->Length > RTL81_MAXIMUM_PACKET_LENGTH) ||
  1405. (Header->Length < RTL81_MINIMUM_PACKET_LENGTH)) {
  1406. EarlyStatus = RTL81_READ_REGISTER8(Device,
  1407. Rtl81RegisterEarlyReceiveStatus);
  1408. if ((EarlyStatus & RTL81_EARLY_RECEIVE_STATUS_OK) != 0) {
  1409. break;
  1410. }
  1411. CommandRegister = RTL81_READ_REGISTER8(Device,
  1412. Rtl81RegisterCommand);
  1413. CommandRegister &= ~RTL81_COMMAND_REGISTER_RECEIVE_ENABLE;
  1414. RTL81_WRITE_REGISTER8(Device,
  1415. Rtl81RegisterCommand,
  1416. CommandRegister);
  1417. CommandRegister |= RTL81_COMMAND_REGISTER_RECEIVE_ENABLE;
  1418. RTL81_WRITE_REGISTER8(Device,
  1419. Rtl81RegisterCommand,
  1420. CommandRegister);
  1421. RTL81_WRITE_REGISTER32(Device,
  1422. Rtl81RegisterReceiveConfiguration,
  1423. RTL81_RECEIVE_CONFIGURATION_DEFAULT_OPTIONS);
  1424. ReadPacketAddress = RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET -
  1425. RTL81_RECEIVE_OFFSET_ADJUSTMENT;
  1426. RTL81_WRITE_REGISTER16(Device,
  1427. Rtl81RegisterReadPacketAddress,
  1428. ReadPacketAddress);
  1429. break;
  1430. }
  1431. //
  1432. // The header indicated a valid packet, try to count these as reaped
  1433. // bytes. If these bytes extend beyond the pre-calculated total, exit
  1434. // the loop now, they packet likely isn't ready.
  1435. //
  1436. BytesReaped += sizeof(RTL81_PACKET_HEADER) + Header->Length;
  1437. if (BytesReaped > MaxBytesToReap) {
  1438. break;
  1439. }
  1440. //
  1441. // Create a network buffer packet to send to the networking core. Get
  1442. // the offset of the actual data by skipping over the header. Wrap
  1443. // around to zero if the current offset went beyond the end.
  1444. //
  1445. CurrentOffset += sizeof(RTL81_PACKET_HEADER);
  1446. if (CurrentOffset >= RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET) {
  1447. CurrentOffset -= RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET;
  1448. }
  1449. //
  1450. // Remove the size of the CRC from the length.
  1451. //
  1452. PacketLength = Header->Length - RTL81_RECEIVE_CRC_LENGTH;
  1453. //
  1454. // Extra space was left at the end of the receive I/O buffer to handle
  1455. // wrapping, so copy any wrapped data to the end of the buffer. Move
  1456. // the current offset forward, accounting for the CRC.
  1457. //
  1458. ASSERT(CurrentOffset < RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET);
  1459. Packet.Buffer = VirtualAddress + CurrentOffset;
  1460. Packet.BufferPhysicalAddress = PhysicalAddress + CurrentOffset;
  1461. WrapOffset = RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET - CurrentOffset;
  1462. if (PacketLength > WrapOffset) {
  1463. WrapLength = PacketLength - WrapOffset;
  1464. RtlCopyMemory(Packet.Buffer + WrapOffset,
  1465. VirtualAddress,
  1466. WrapLength);
  1467. CurrentOffset = WrapLength + RTL81_RECEIVE_CRC_LENGTH;
  1468. } else {
  1469. CurrentOffset += PacketLength + RTL81_RECEIVE_CRC_LENGTH;
  1470. }
  1471. if (CurrentOffset >= RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET) {
  1472. CurrentOffset -= RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET;
  1473. }
  1474. //
  1475. // Remove the size of the CRC from the length.
  1476. //
  1477. Packet.BufferSize = PacketLength;
  1478. Packet.DataSize = PacketLength;
  1479. Packet.DataOffset = 0;
  1480. Packet.FooterOffset = PacketLength;
  1481. NetProcessReceivedPacket(Device->NetworkLink, &Packet);
  1482. //
  1483. // Move past this packet. The current offset is set to the end of the
  1484. // CRC. Just align it up and then notify the hardware. Count these as
  1485. // bytes reaped.
  1486. //
  1487. AlignedOffset = ALIGN_RANGE_UP(CurrentOffset,
  1488. RTL81_RECEIVE_RING_BUFFER_ALIGNMENT);
  1489. if (AlignedOffset >= RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET) {
  1490. AlignedOffset = 0;
  1491. BytesReaped += RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET -
  1492. CurrentOffset;
  1493. } else {
  1494. BytesReaped += AlignedOffset - CurrentOffset;
  1495. }
  1496. CurrentOffset = AlignedOffset;
  1497. if (CurrentOffset >= RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET) {
  1498. CurrentOffset -= RTL81_MAXIMUM_RECEIVE_RING_BUFFER_OFFSET;
  1499. }
  1500. //
  1501. // Don't update the current offset with the adjustment as the next
  1502. // packet should be sitting at the offset before the adjustment.
  1503. //
  1504. ReadPacketAddress = CurrentOffset - RTL81_RECEIVE_OFFSET_ADJUSTMENT;
  1505. RTL81_WRITE_REGISTER16(Device,
  1506. Rtl81RegisterReadPacketAddress,
  1507. ReadPacketAddress);
  1508. //
  1509. // Update the command register status now that a packet has been
  1510. // processed. The buffer may be empty.
  1511. //
  1512. CommandRegister = RTL81_READ_REGISTER8(Device, Rtl81RegisterCommand);
  1513. }
  1514. return;
  1515. }
  1516. VOID
  1517. Rtl81pReapReceivedFramesDefault (
  1518. PRTL81_DEVICE Device
  1519. )
  1520. /*++
  1521. Routine Description:
  1522. This routine reaps received frames from receive descriptors of the newer
  1523. RTL8139C+, RTL8168, and similar chips. It then notifies the core networking
  1524. driver about a packet's arrival.
  1525. Arguments:
  1526. Device - Supplies a pointer to the RTL81xx device.
  1527. Return Value:
  1528. None.
  1529. --*/
  1530. {
  1531. ULONG Command;
  1532. PRTL81_DEFAULT_DATA DefaultData;
  1533. PRTL81_RECEIVE_DESCRIPTOR Descriptor;
  1534. ULONG Flags;
  1535. USHORT NextToReap;
  1536. NET_PACKET_BUFFER Packet;
  1537. ULONG Protocol;
  1538. ULONG SegmentFlags;
  1539. ULONG Size;
  1540. ULONG VlanTag;
  1541. ASSERT((Device->Flags & RTL81_FLAG_TRANSMIT_MODE_LEGACY) == 0);
  1542. Packet.IoBuffer = NULL;
  1543. Packet.ListEntry.Next = NULL;
  1544. Descriptor = NULL;
  1545. DefaultData = &(Device->U.DefaultData);
  1546. SegmentFlags = RTL81_RECEIVE_DESCRIPTOR_COMMAND_FIRST_SEGMENT |
  1547. RTL81_RECEIVE_DESCRIPTOR_COMMAND_LAST_SEGMENT;
  1548. while (TRUE) {
  1549. //
  1550. // If this isn't the first time around, advance the next to index and
  1551. // reset the current descriptor.
  1552. //
  1553. if (Descriptor != NULL) {
  1554. Command = RTL81_RECEIVE_DESCRIPTOR_DEFAULT_COMMAND;
  1555. DefaultData->ReceiveNextToReap += 1;
  1556. if (DefaultData->ReceiveNextToReap ==
  1557. DefaultData->ReceiveDescriptorCount) {
  1558. Command |= RTL81_RECEIVE_DESCRIPTOR_COMMAND_END_OF_RING;
  1559. DefaultData->ReceiveNextToReap = 0;
  1560. }
  1561. Descriptor->Command = Command;
  1562. }
  1563. //
  1564. // Try to harvest the packet in te next descriptor.
  1565. //
  1566. NextToReap = DefaultData->ReceiveNextToReap;
  1567. Descriptor = &(DefaultData->ReceiveDescriptor[NextToReap]);
  1568. //
  1569. // If the descriptor is still in use by the hardware, then stop.
  1570. //
  1571. Command = Descriptor->Command;
  1572. if ((Command & RTL81_RECEIVE_DESCRIPTOR_COMMAND_OWN) != 0) {
  1573. break;
  1574. }
  1575. //
  1576. // Rtl8168C and above do not support multi-segment packets. Discard
  1577. // such packets.
  1578. //
  1579. if (((Device->Flags & RTL81_FLAG_MULTI_SEGMENT_SUPPORT) == 0) &&
  1580. ((Command & SegmentFlags) != SegmentFlags)) {
  1581. continue;
  1582. }
  1583. //
  1584. // This is a valid packet that needs to be reaped. Only single
  1585. // packets are supported.
  1586. //
  1587. ASSERT((Command & SegmentFlags) == SegmentFlags);
  1588. //
  1589. // The command bits differ between the RTL8139C+ and newer chips.
  1590. // Handle that now.
  1591. //
  1592. if ((Device->Flags & RTL81_FLAG_RECEIVE_COMMAND_LEGACY) != 0) {
  1593. Size = (Command & RTL81_RECEIVE_DESCRIPTOR_COMMAND_SIZE_MASK) >>
  1594. RTL81_RECEIVE_DESCRIPTOR_COMMAND_SIZE_SHIFT;
  1595. } else {
  1596. Size = (Command &
  1597. RTL81_RECEIVE_DESCRIPTOR_COMMAND_LARGE_SIZE_MASK) >>
  1598. RTL81_RECEIVE_DESCRIPTOR_COMMAND_LARGE_SIZE_SHIFT;
  1599. //
  1600. // With the size and top four bits out of the way, modify the
  1601. // command variable so that the values match those of the older
  1602. // model.
  1603. //
  1604. Command >>= RTL81_RECEIVE_DESCRIPTOR_COMMAND_SHIFT;
  1605. }
  1606. //
  1607. // Skip the packet if any error flags are set.
  1608. //
  1609. if ((Command & RTL81_RECEIVE_DESCRIPTOR_COMMAND_ERROR_SUMMARY) != 0) {
  1610. continue;
  1611. }
  1612. //
  1613. // Collect the checksum flags, passing the packet to the networking
  1614. // core even if the checksum failed.
  1615. //
  1616. Flags = 0;
  1617. Protocol = (Command & RTL81_RECEIVE_DESCRIPTOR_COMMAND_PROTOCOL_MASK) >>
  1618. RTL81_RECEIVE_DESCRIPTOR_COMMAND_PROTOCOL_SHIFT;
  1619. if (Protocol != 0) {
  1620. VlanTag = Descriptor->VlanTag;
  1621. if (((Device->Flags & RTL81_FLAG_CHECKSUM_OFFLOAD_VLAN) == 0) ||
  1622. ((VlanTag & RTL81_RECEIVE_DESCRIPTOR_VLAN_IP4) != 0)) {
  1623. Flags |= NET_PACKET_FLAG_IP_CHECKSUM_OFFLOAD;
  1624. if (RTL81_RECEIVE_IP_CHECKSUM_FAILURE(Command) != FALSE) {
  1625. Flags |= NET_PACKET_FLAG_IP_CHECKSUM_FAILED;
  1626. }
  1627. }
  1628. if (Protocol == RTL81_RECEIVE_DESCRIPTOR_COMMAND_PROTOCOL_UDP_IP) {
  1629. Flags |= NET_PACKET_FLAG_UDP_CHECKSUM_OFFLOAD;
  1630. if (RTL81_RECEIVE_UDP_CHECKSUM_FAILURE(Command) != FALSE) {
  1631. Flags |= NET_PACKET_FLAG_UDP_CHECKSUM_FAILED;
  1632. }
  1633. } else if (Protocol ==
  1634. RTL81_RECEIVE_DESCRIPTOR_COMMAND_PROTOCOL_TCP_IP) {
  1635. Flags |= NET_PACKET_FLAG_TCP_CHECKSUM_OFFLOAD;
  1636. if (RTL81_RECEIVE_TCP_CHECKSUM_FAILURE(Command) != FALSE) {
  1637. Flags |= NET_PACKET_FLAG_TCP_CHECKSUM_FAILED;
  1638. }
  1639. }
  1640. }
  1641. Packet.Buffer = DefaultData->ReceivePacketData +
  1642. (NextToReap * RTL81_RECEIVE_BUFFER_DATA_SIZE);
  1643. Packet.BufferPhysicalAddress = Descriptor->PhysicalAddress;
  1644. Packet.Flags = Flags;
  1645. //
  1646. // Discard the CRC from the size.
  1647. //
  1648. Size -= RTL81_RECEIVE_CRC_LENGTH;
  1649. Packet.BufferSize = Size;
  1650. Packet.DataSize = Size;
  1651. Packet.DataOffset = 0;
  1652. Packet.FooterOffset = Size;
  1653. NetProcessReceivedPacket(Device->NetworkLink, &Packet);
  1654. }
  1655. return;
  1656. }
  1657. KSTATUS
  1658. Rtl81pReadMacAddress (
  1659. PRTL81_DEVICE Device
  1660. )
  1661. /*++
  1662. Routine Description:
  1663. This routine reads the MAC address out of the EEPROM on the RTL81xx. The
  1664. MAC address will be stored in the device structure.
  1665. Arguments:
  1666. Device - Supplies a pointer to the RTL81xx device.
  1667. Return Value:
  1668. Status code.
  1669. --*/
  1670. {
  1671. RTL81_REGISTER AddressRegister;
  1672. ULONG Index;
  1673. USHORT MacValue;
  1674. //
  1675. // The MAC address is in the individual address registers. There is one
  1676. // byte in each but two can be read at a time as they are sequential
  1677. // registers.
  1678. //
  1679. AddressRegister = Rtl81RegisterId0;
  1680. for (Index = 0; Index < sizeof(Device->MacAddress); Index += 2) {
  1681. MacValue = RTL81_READ_REGISTER16(Device, AddressRegister);
  1682. Device->MacAddress[Index] = (BYTE)MacValue;
  1683. Device->MacAddress[Index + 1] = (BYTE)(MacValue >> BITS_PER_BYTE);
  1684. AddressRegister += 2;
  1685. }
  1686. //
  1687. // Check to determine if this is a valid MAC address.
  1688. //
  1689. if (NetIsEthernetAddressValid(Device->MacAddress) == FALSE) {
  1690. return STATUS_INVALID_ADDRESS;
  1691. }
  1692. return STATUS_SUCCESS;
  1693. }
  1694. KSTATUS
  1695. Rtl81pReadMdio (
  1696. PRTL81_DEVICE Device,
  1697. RTL81_MII_REGISTER Register,
  1698. PULONG Data
  1699. )
  1700. /*++
  1701. Routine Description:
  1702. This routine performs an MDIO register read.
  1703. Arguments:
  1704. Device - Supplies a pointer to the device.
  1705. Register - Supplies the register to read.
  1706. Data - Supplies a pointer where the register contents will be returned on
  1707. success.
  1708. Return Value:
  1709. Status code.
  1710. --*/
  1711. {
  1712. ULONGLONG CurrentTime;
  1713. ULONG RegisterValue;
  1714. ULONGLONG Timeout;
  1715. ULONGLONG TimeoutTicks;
  1716. TimeoutTicks = HlQueryTimeCounterFrequency() * RTL81_DEVICE_TIMEOUT;
  1717. ASSERT(Register < Rtl81MiiRegisterMax);
  1718. RegisterValue = RTL81_MII_ACCESS_READ |
  1719. ((Register << RTL81_MII_ACCESS_REGISTER_SHIFT) &
  1720. RTL81_MII_ACCESS_REGISTER_MASK);
  1721. RTL81_WRITE_REGISTER32(Device, Rtl81RegisterMiiAccess, RegisterValue);
  1722. CurrentTime = KeGetRecentTimeCounter();
  1723. Timeout = CurrentTime + TimeoutTicks;
  1724. do {
  1725. KeDelayExecution(FALSE, FALSE, 100);
  1726. RegisterValue = RTL81_READ_REGISTER32(Device, Rtl81RegisterMiiAccess);
  1727. if ((RegisterValue & RTL81_MII_ACCESS_COMPLETE_MASK) ==
  1728. RTL81_MII_ACCESS_READ_COMPLETE) {
  1729. *Data = (RegisterValue & RTL81_MII_ACCESS_DATA_MASK) >>
  1730. RTL81_MII_ACCESS_DATA_SHIFT;
  1731. KeDelayExecution(FALSE, FALSE, 20);
  1732. break;
  1733. }
  1734. CurrentTime = KeGetRecentTimeCounter();
  1735. } while (CurrentTime <= Timeout);
  1736. if (CurrentTime > Timeout) {
  1737. return STATUS_TIMEOUT;
  1738. }
  1739. return STATUS_SUCCESS;
  1740. }
  1741. KSTATUS
  1742. Rtl81pWriteMdio (
  1743. PRTL81_DEVICE Device,
  1744. RTL81_MII_REGISTER Register,
  1745. ULONG Data
  1746. )
  1747. /*++
  1748. Routine Description:
  1749. This routine performs an MDIO register write.
  1750. Arguments:
  1751. Device - Supplies a pointer to the device.
  1752. Register - Supplies the register to read.
  1753. Data - Supplies the data to write to the register.
  1754. Return Value:
  1755. Status code.
  1756. --*/
  1757. {
  1758. ULONGLONG CurrentTime;
  1759. ULONG RegisterValue;
  1760. ULONGLONG Timeout;
  1761. ULONGLONG TimeoutTicks;
  1762. TimeoutTicks = HlQueryTimeCounterFrequency() * RTL81_DEVICE_TIMEOUT;
  1763. ASSERT(Register < Rtl81MiiRegisterMax);
  1764. ASSERT((Data & ~RTL81_MII_ACCESS_DATA_MASK) == 0);
  1765. RegisterValue = RTL81_MII_ACCESS_WRITE |
  1766. ((Register << RTL81_MII_ACCESS_REGISTER_SHIFT) &
  1767. RTL81_MII_ACCESS_REGISTER_MASK) |
  1768. Data;
  1769. RTL81_WRITE_REGISTER32(Device, Rtl81RegisterMiiAccess, RegisterValue);
  1770. CurrentTime = KeGetRecentTimeCounter();
  1771. Timeout = CurrentTime + TimeoutTicks;
  1772. do {
  1773. KeDelayExecution(FALSE, FALSE, 100);
  1774. RegisterValue = RTL81_READ_REGISTER32(Device, Rtl81RegisterMiiAccess);
  1775. if ((RegisterValue & RTL81_MII_ACCESS_COMPLETE_MASK) ==
  1776. RTL81_MII_ACCESS_WRITE_COMPLETE) {
  1777. KeDelayExecution(FALSE, FALSE, 20);
  1778. break;
  1779. }
  1780. CurrentTime = KeGetRecentTimeCounter();
  1781. } while (CurrentTime <= Timeout);
  1782. if (CurrentTime > Timeout) {
  1783. return STATUS_TIMEOUT;
  1784. }
  1785. return STATUS_SUCCESS;
  1786. }