rtlw81.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  1. /*++
  2. Copyright (c) 2015 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. rtlw81.c
  5. Abstract:
  6. This module implements support for the driver portion of the RTL81xx
  7. family of USB WIFI Controllers.
  8. Author:
  9. Chris Stevens 7-Oct-2015
  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/net80211.h>
  19. #include <minoca/usb/usb.h>
  20. #include "rtlw81.h"
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. //
  25. // Known vendors and products.
  26. //
  27. #define RTLW81_USB_DEVICE_ID_FORMAT "VID_%x&PID_%x"
  28. #define RTLW81_VENDOR_DLINK 0x2001
  29. #define RTLW81_DLINK_DWA125D1 0x330F
  30. #define RTLW81_DLINK_DWA123D1 0x3310
  31. #define RTLW81_VENDOR_ELECOM 0x056E
  32. #define RTLW81_ELECOM_WDC150SU2M 0x4008
  33. #define RTLW81_VENDOR_REALTEK 0x0BDA
  34. #define RTLW81_REALTEK_RTL8188ETV 0x0179
  35. #define RTLW81_REALTEK_RTL8188EU 0x8179
  36. //
  37. // ------------------------------------------------------ Data Type Definitions
  38. //
  39. //
  40. // ----------------------------------------------- Internal Function Prototypes
  41. //
  42. KSTATUS
  43. Rtlw81AddDevice (
  44. PVOID Driver,
  45. PSTR DeviceId,
  46. PSTR ClassId,
  47. PSTR CompatibleIds,
  48. PVOID DeviceToken
  49. );
  50. VOID
  51. Rtlw81DispatchStateChange (
  52. PIRP Irp,
  53. PVOID DeviceContext,
  54. PVOID IrpContext
  55. );
  56. VOID
  57. Rtlw81DispatchOpen (
  58. PIRP Irp,
  59. PVOID DeviceContext,
  60. PVOID IrpContext
  61. );
  62. VOID
  63. Rtlw81DispatchClose (
  64. PIRP Irp,
  65. PVOID DeviceContext,
  66. PVOID IrpContext
  67. );
  68. VOID
  69. Rtlw81DispatchIo (
  70. PIRP Irp,
  71. PVOID DeviceContext,
  72. PVOID IrpContext
  73. );
  74. VOID
  75. Rtlw81DispatchSystemControl (
  76. PIRP Irp,
  77. PVOID DeviceContext,
  78. PVOID IrpContext
  79. );
  80. VOID
  81. Rtlw81DestroyLink (
  82. PVOID DeviceContext
  83. );
  84. KSTATUS
  85. Rtlw81pInitializeDeviceStructures (
  86. PVOID OsDevice,
  87. PRTLW81_DEVICE *NewDevice
  88. );
  89. VOID
  90. Rtlw81pDestroyDeviceStructures (
  91. PRTLW81_DEVICE Device
  92. );
  93. VOID
  94. Rtlw81pDeviceAddReference (
  95. PRTLW81_DEVICE Device
  96. );
  97. VOID
  98. Rtlw81pDeviceReleaseReference (
  99. PRTLW81_DEVICE Device
  100. );
  101. KSTATUS
  102. Rtlw81pSetUpUsbDevice (
  103. PRTLW81_DEVICE Device
  104. );
  105. KSTATUS
  106. Rtlw81pStartDevice (
  107. PIRP Irp,
  108. PRTLW81_DEVICE Device
  109. );
  110. KSTATUS
  111. Rtlw81pStopDevice (
  112. PIRP Irp,
  113. PRTLW81_DEVICE Device
  114. );
  115. //
  116. // -------------------------------------------------------------------- Globals
  117. //
  118. PDRIVER Rtlw81Driver = NULL;
  119. //
  120. // Store the default rate information for the RTL81xx wireless devices.
  121. //
  122. UCHAR RtlwDefaultRates[] = {
  123. NET80211_RATE_BASIC | 0x02,
  124. NET80211_RATE_BASIC | 0x04,
  125. NET80211_RATE_BASIC | 0x0B,
  126. NET80211_RATE_BASIC | 0x16,
  127. 0x0C,
  128. 0x12,
  129. 0x18,
  130. 0x24,
  131. 0x30,
  132. 0x48,
  133. 0x60,
  134. 0x6C
  135. };
  136. NET80211_RATE_INFORMATION RtlwDefaultRateInformation = {
  137. sizeof(RtlwDefaultRates) / sizeof(RtlwDefaultRates[0]),
  138. RtlwDefaultRates
  139. };
  140. //
  141. // ------------------------------------------------------------------ Functions
  142. //
  143. KSTATUS
  144. DriverEntry (
  145. PDRIVER Driver
  146. )
  147. /*++
  148. Routine Description:
  149. This routine is the entry point for the SMSC95xx driver. It registers its
  150. other dispatch functions, and performs driver-wide initialization.
  151. Arguments:
  152. Driver - Supplies a pointer to the driver object.
  153. Return Value:
  154. STATUS_SUCCESS on success.
  155. Failure code on error.
  156. --*/
  157. {
  158. DRIVER_FUNCTION_TABLE FunctionTable;
  159. KSTATUS Status;
  160. Rtlw81Driver = Driver;
  161. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  162. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  163. FunctionTable.AddDevice = Rtlw81AddDevice;
  164. FunctionTable.DispatchStateChange = Rtlw81DispatchStateChange;
  165. FunctionTable.DispatchOpen = Rtlw81DispatchOpen;
  166. FunctionTable.DispatchClose = Rtlw81DispatchClose;
  167. FunctionTable.DispatchIo = Rtlw81DispatchIo;
  168. FunctionTable.DispatchSystemControl = Rtlw81DispatchSystemControl;
  169. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  170. return Status;
  171. }
  172. KSTATUS
  173. Rtlw81AddDevice (
  174. PVOID Driver,
  175. PSTR DeviceId,
  176. PSTR ClassId,
  177. PSTR CompatibleIds,
  178. PVOID DeviceToken
  179. )
  180. /*++
  181. Routine Description:
  182. This routine is called when a device is detected for which the SMSC95xx
  183. driver acts as the function driver. The driver will attach itself to the
  184. stack.
  185. Arguments:
  186. Driver - Supplies a pointer to the driver being called.
  187. DeviceId - Supplies a pointer to a string with the device ID.
  188. ClassId - Supplies a pointer to a string containing the device's class ID.
  189. CompatibleIds - Supplies a pointer to a string containing device IDs
  190. that would be compatible with this device.
  191. DeviceToken - Supplies an opaque token that the driver can use to identify
  192. the device in the system. This token should be used when attaching to
  193. the stack.
  194. Return Value:
  195. STATUS_SUCCESS on success.
  196. Failure code if the driver was unsuccessful in attaching itself.
  197. --*/
  198. {
  199. PRTLW81_DEVICE Device;
  200. ULONG ItemsScanned;
  201. KSTATUS Status;
  202. USHORT UsbProductId;
  203. USHORT UsbVendorId;
  204. Status = Rtlw81pInitializeDeviceStructures(DeviceToken, &Device);
  205. if (!KSUCCESS(Status)) {
  206. goto AddDeviceEnd;
  207. }
  208. //
  209. // Detect variants by USB vendor and product ID.
  210. //
  211. Status = RtlStringScan(DeviceId,
  212. RtlStringLength(DeviceId) + 1,
  213. RTLW81_USB_DEVICE_ID_FORMAT,
  214. sizeof(RTLW81_USB_DEVICE_ID_FORMAT),
  215. CharacterEncodingDefault,
  216. &ItemsScanned,
  217. &UsbVendorId,
  218. &UsbProductId);
  219. if (!KSUCCESS(Status)) {
  220. goto AddDeviceEnd;
  221. }
  222. if (ItemsScanned != 2) {
  223. Status = STATUS_INVALID_CONFIGURATION;
  224. goto AddDeviceEnd;
  225. }
  226. switch (UsbVendorId) {
  227. case RTLW81_VENDOR_DLINK:
  228. if ((UsbProductId == RTLW81_DLINK_DWA123D1) ||
  229. (UsbProductId == RTLW81_DLINK_DWA125D1)) {
  230. Device->Flags |= RTLW81_FLAG_8188E;
  231. }
  232. break;
  233. case RTLW81_VENDOR_ELECOM:
  234. if (UsbProductId == RTLW81_ELECOM_WDC150SU2M) {
  235. Device->Flags |= RTLW81_FLAG_8188E;
  236. }
  237. break;
  238. case RTLW81_VENDOR_REALTEK:
  239. if ((UsbProductId == RTLW81_REALTEK_RTL8188ETV) ||
  240. (UsbProductId == RTLW81_REALTEK_RTL8188EU)) {
  241. Device->Flags |= RTLW81_FLAG_8188E;
  242. }
  243. break;
  244. default:
  245. break;
  246. }
  247. Status = IoAttachDriverToDevice(Driver, DeviceToken, Device);
  248. if (!KSUCCESS(Status)) {
  249. goto AddDeviceEnd;
  250. }
  251. AddDeviceEnd:
  252. if (!KSUCCESS(Status)) {
  253. if (Device != NULL) {
  254. Rtlw81pDeviceReleaseReference(Device);
  255. }
  256. }
  257. return Status;
  258. }
  259. VOID
  260. Rtlw81DispatchStateChange (
  261. PIRP Irp,
  262. PVOID DeviceContext,
  263. PVOID IrpContext
  264. )
  265. /*++
  266. Routine Description:
  267. This routine handles State Change IRPs.
  268. Arguments:
  269. Irp - Supplies a pointer to the I/O request packet.
  270. DeviceContext - Supplies the context pointer supplied by the driver when it
  271. attached itself to the driver stack. Presumably this pointer contains
  272. driver-specific device context.
  273. IrpContext - Supplies the context pointer supplied by the driver when
  274. the IRP was created.
  275. Return Value:
  276. None.
  277. --*/
  278. {
  279. KSTATUS Status;
  280. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  281. if (Irp->Direction == IrpUp) {
  282. switch (Irp->MinorCode) {
  283. case IrpMinorQueryResources:
  284. case IrpMinorQueryChildren:
  285. IoCompleteIrp(Rtlw81Driver, Irp, STATUS_SUCCESS);
  286. break;
  287. case IrpMinorStartDevice:
  288. Status = Rtlw81pStartDevice(Irp, DeviceContext);
  289. if (!KSUCCESS(Status)) {
  290. IoCompleteIrp(Rtlw81Driver, Irp, Status);
  291. }
  292. break;
  293. case IrpMinorRemoveDevice:
  294. Status = Rtlw81pStopDevice(Irp, DeviceContext);
  295. if (!KSUCCESS(Status)) {
  296. IoCompleteIrp(Rtlw81Driver, Irp, Status);
  297. break;
  298. }
  299. break;
  300. default:
  301. break;
  302. }
  303. }
  304. return;
  305. }
  306. VOID
  307. Rtlw81DispatchOpen (
  308. PIRP Irp,
  309. PVOID DeviceContext,
  310. PVOID IrpContext
  311. )
  312. /*++
  313. Routine Description:
  314. This routine handles Open IRPs.
  315. Arguments:
  316. Irp - Supplies a pointer to the I/O request packet.
  317. DeviceContext - Supplies the context pointer supplied by the driver when it
  318. attached itself to the driver stack. Presumably this pointer contains
  319. driver-specific device context.
  320. IrpContext - Supplies the context pointer supplied by the driver when
  321. the IRP was created.
  322. Return Value:
  323. None.
  324. --*/
  325. {
  326. return;
  327. }
  328. VOID
  329. Rtlw81DispatchClose (
  330. PIRP Irp,
  331. PVOID DeviceContext,
  332. PVOID IrpContext
  333. )
  334. /*++
  335. Routine Description:
  336. This routine handles Close IRPs.
  337. Arguments:
  338. Irp - Supplies a pointer to the I/O request packet.
  339. DeviceContext - Supplies the context pointer supplied by the driver when it
  340. attached itself to the driver stack. Presumably this pointer contains
  341. driver-specific device context.
  342. IrpContext - Supplies the context pointer supplied by the driver when
  343. the IRP was created.
  344. Return Value:
  345. None.
  346. --*/
  347. {
  348. return;
  349. }
  350. VOID
  351. Rtlw81DispatchIo (
  352. PIRP Irp,
  353. PVOID DeviceContext,
  354. PVOID IrpContext
  355. )
  356. /*++
  357. Routine Description:
  358. This routine handles I/O IRPs.
  359. Arguments:
  360. Irp - Supplies a pointer to the I/O request packet.
  361. DeviceContext - Supplies the context pointer supplied by the driver when it
  362. attached itself to the driver stack. Presumably this pointer contains
  363. driver-specific device context.
  364. IrpContext - Supplies the context pointer supplied by the driver when
  365. the IRP was created.
  366. Return Value:
  367. None.
  368. --*/
  369. {
  370. return;
  371. }
  372. VOID
  373. Rtlw81DispatchSystemControl (
  374. PIRP Irp,
  375. PVOID DeviceContext,
  376. PVOID IrpContext
  377. )
  378. /*++
  379. Routine Description:
  380. This routine handles System Control IRPs.
  381. Arguments:
  382. Irp - Supplies a pointer to the I/O request packet.
  383. DeviceContext - Supplies the context pointer supplied by the driver when it
  384. attached itself to the driver stack. Presumably this pointer contains
  385. driver-specific device context.
  386. IrpContext - Supplies the context pointer supplied by the driver when
  387. the IRP was created.
  388. Return Value:
  389. None.
  390. --*/
  391. {
  392. PRTLW81_DEVICE Device;
  393. PSYSTEM_CONTROL_DEVICE_INFORMATION DeviceInformationRequest;
  394. KSTATUS Status;
  395. ASSERT(Irp->MajorCode == IrpMajorSystemControl);
  396. Device = DeviceContext;
  397. if (Irp->Direction == IrpDown) {
  398. switch (Irp->MinorCode) {
  399. case IrpMinorSystemControlDeviceInformation:
  400. DeviceInformationRequest = Irp->U.SystemControl.SystemContext;
  401. Status = Net80211GetSetLinkDeviceInformation(
  402. Device->Net80211Link,
  403. &(DeviceInformationRequest->Uuid),
  404. DeviceInformationRequest->Data,
  405. &(DeviceInformationRequest->DataSize),
  406. DeviceInformationRequest->Set);
  407. IoCompleteIrp(Rtlw81Driver, Irp, Status);
  408. break;
  409. default:
  410. break;
  411. }
  412. }
  413. return;
  414. }
  415. KSTATUS
  416. Rtlw81pAddNetworkDevice (
  417. PRTLW81_DEVICE Device
  418. )
  419. /*++
  420. Routine Description:
  421. This routine adds the device to 802.11 core networking's available links.
  422. Arguments:
  423. Device - Supplies a pointer to the device to add.
  424. Return Value:
  425. Status code.
  426. --*/
  427. {
  428. NET80211_LINK_PROPERTIES Properties;
  429. KSTATUS Status;
  430. if (Device->Net80211Link != NULL) {
  431. Status = STATUS_SUCCESS;
  432. goto AddNetworkDeviceEnd;
  433. }
  434. //
  435. // Add a link to the 802.11 core networking library.
  436. //
  437. RtlZeroMemory(&Properties, sizeof(NET80211_LINK_PROPERTIES));
  438. Properties.Version = NET80211_LINK_PROPERTIES_VERSION;
  439. Properties.TransmitAlignment = MmGetIoBufferAlignment();
  440. Properties.Device = Device->OsDevice;
  441. Properties.DeviceContext = Device;
  442. Properties.MaxChannel = RTLW81_MAX_CHANNEL;
  443. Properties.Capabilities = NET80211_CAPABILITY_FLAG_SHORT_PREAMBLE |
  444. NET80211_CAPABILITY_FLAG_SHORT_SLOT_TIME;
  445. Properties.PacketSizeInformation.MaxPacketSize = RTLW81_MAX_PACKET_SIZE;
  446. Properties.PacketSizeInformation.HeaderSize = RTLW81_TRANSMIT_HEADER_SIZE;
  447. Properties.MaxPhysicalAddress = MAX_ULONG;
  448. Properties.PhysicalAddress.Domain = NetDomain80211;
  449. RtlCopyMemory(&(Properties.PhysicalAddress.Address),
  450. &(Device->MacAddress),
  451. sizeof(Device->MacAddress));
  452. Properties.SupportedRates = &RtlwDefaultRateInformation;
  453. Properties.Interface.Send = Rtlw81Send;
  454. Properties.Interface.GetSetInformation = Rtlw81GetSetInformation;
  455. Properties.Interface.DestroyLink = Rtlw81DestroyLink;
  456. Properties.Interface.SetChannel = Rtlw81SetChannel;
  457. Properties.Interface.SetState = Rtlw81SetState;
  458. Status = Net80211AddLink(&Properties, &(Device->Net80211Link));
  459. if (!KSUCCESS(Status)) {
  460. goto AddNetworkDeviceEnd;
  461. }
  462. //
  463. // The 802.11 core now has a pointer to the device context. Add a reference
  464. // for it.
  465. //
  466. Rtlw81pDeviceAddReference(Device);
  467. AddNetworkDeviceEnd:
  468. if (!KSUCCESS(Status)) {
  469. if (Device->Net80211Link != NULL) {
  470. Net80211RemoveLink(Device->Net80211Link);
  471. Device->Net80211Link = NULL;
  472. }
  473. }
  474. return Status;
  475. }
  476. VOID
  477. Rtlw81DestroyLink (
  478. PVOID DeviceContext
  479. )
  480. /*++
  481. Routine Description:
  482. This routine notifies the device layer that the 802.11 core is in the
  483. process of destroying the link and will no longer call into the device for
  484. this link. This allows the device layer to release any context that was
  485. supporting the device link interface.
  486. Arguments:
  487. DeviceContext - Supplies a pointer to the device context associated with
  488. the link being destroyed.
  489. Return Value:
  490. None.
  491. --*/
  492. {
  493. Rtlw81pDeviceReleaseReference(DeviceContext);
  494. return;
  495. }
  496. //
  497. // --------------------------------------------------------- Internal Functions
  498. //
  499. KSTATUS
  500. Rtlw81pInitializeDeviceStructures (
  501. PVOID OsDevice,
  502. PRTLW81_DEVICE *NewDevice
  503. )
  504. /*++
  505. Routine Description:
  506. This routine initializes an RTLW81xx device.
  507. Arguments:
  508. OsDevice - Supplies a pointer to the system token that represents this
  509. device.
  510. NewDevice - Supplies a pointer where the new structure will be returned.
  511. Return Value:
  512. Status code.
  513. --*/
  514. {
  515. ULONG BufferAlignment;
  516. PRTLW81_DEVICE Device;
  517. ULONG Index;
  518. ULONG IoBufferFlags;
  519. UINTN IoBufferSize;
  520. ULONG MaxBulkInTransferSize;
  521. ULONG MaxControlSize;
  522. PHYSICAL_ADDRESS PhysicalAddress;
  523. KSTATUS Status;
  524. PUSB_TRANSFER UsbTransfer;
  525. PVOID VirtualAddress;
  526. Device = MmAllocatePagedPool(sizeof(RTLW81_DEVICE), RTLW81_ALLOCATION_TAG);
  527. if (Device == NULL) {
  528. Status = STATUS_INSUFFICIENT_RESOURCES;
  529. goto InitializeDeviceStructuresEnd;
  530. }
  531. RtlZeroMemory(Device, sizeof(RTLW81_DEVICE));
  532. Device->OsDevice = OsDevice;
  533. Device->UsbCoreHandle = INVALID_HANDLE;
  534. Device->ReferenceCount = 1;
  535. for (Index = 0; Index < RTLW81_MAX_BULK_OUT_ENDPOINT_COUNT; Index += 1) {
  536. INITIALIZE_LIST_HEAD(&(Device->BulkOutFreeTransferList[Index]));
  537. }
  538. Device->BulkOutListLock = KeCreateQueuedLock();
  539. if (Device->BulkOutListLock == NULL) {
  540. Status = STATUS_INSUFFICIENT_RESOURCES;
  541. goto InitializeDeviceStructuresEnd;
  542. }
  543. //
  544. // Attempt to attach to the USB core.
  545. //
  546. Status = UsbDriverAttach(OsDevice, Rtlw81Driver, &(Device->UsbCoreHandle));
  547. if (!KSUCCESS(Status)) {
  548. goto InitializeDeviceStructuresEnd;
  549. }
  550. Status = Rtlw81pSetUpUsbDevice(Device);
  551. if (!KSUCCESS(Status)) {
  552. goto InitializeDeviceStructuresEnd;
  553. }
  554. //
  555. // Create an I/O buffer for the control and receive transfers.
  556. //
  557. BufferAlignment = MmGetIoBufferAlignment();
  558. MaxBulkInTransferSize = ALIGN_RANGE_UP(RTLW81_BULK_IN_TRANSFER_SIZE,
  559. BufferAlignment);
  560. MaxControlSize = ALIGN_RANGE_UP(RTLW81_MAX_CONTROL_TRANSFER_SIZE,
  561. BufferAlignment);
  562. IoBufferSize = (MaxBulkInTransferSize * RTLW81_BULK_IN_TRANSFER_COUNT) +
  563. MaxControlSize;
  564. IoBufferFlags = IO_BUFFER_FLAG_PHYSICALLY_CONTIGUOUS;
  565. Device->IoBuffer = MmAllocateNonPagedIoBuffer(0,
  566. MAX_ULONG,
  567. BufferAlignment,
  568. IoBufferSize,
  569. IoBufferFlags);
  570. if (Device->IoBuffer == NULL) {
  571. Status = STATUS_INSUFFICIENT_RESOURCES;
  572. goto InitializeDeviceStructuresEnd;
  573. }
  574. ASSERT(Device->IoBuffer->FragmentCount == 1);
  575. ASSERT(Device->IoBuffer->Fragment[0].VirtualAddress != NULL);
  576. PhysicalAddress = Device->IoBuffer->Fragment[0].PhysicalAddress;
  577. VirtualAddress = Device->IoBuffer->Fragment[0].VirtualAddress;
  578. //
  579. // Set up the bulk in transfers that are used to receive packets.
  580. //
  581. for (Index = 0; Index < RTLW81_BULK_IN_TRANSFER_COUNT; Index += 1) {
  582. UsbTransfer = UsbAllocateTransfer(Device->UsbCoreHandle,
  583. Device->BulkInEndpoint,
  584. RTLW81_BULK_IN_TRANSFER_SIZE,
  585. 0);
  586. if (UsbTransfer == NULL) {
  587. Status = STATUS_INSUFFICIENT_RESOURCES;
  588. goto InitializeDeviceStructuresEnd;
  589. }
  590. UsbTransfer->Buffer = VirtualAddress;
  591. UsbTransfer->BufferPhysicalAddress = PhysicalAddress;
  592. UsbTransfer->Direction = UsbTransferDirectionIn;
  593. UsbTransfer->Length = RTLW81_BULK_IN_TRANSFER_SIZE;
  594. UsbTransfer->BufferActualLength = MaxBulkInTransferSize;
  595. UsbTransfer->UserData = Device;
  596. UsbTransfer->CallbackRoutine = Rtlw81BulkInTransferCompletion;
  597. Device->BulkInTransfer[Index] = UsbTransfer;
  598. PhysicalAddress += MaxBulkInTransferSize;
  599. VirtualAddress += MaxBulkInTransferSize;
  600. }
  601. //
  602. // Set up the control transfer that's used for register reads and writes.
  603. //
  604. Device->ControlTransfer = UsbAllocateTransfer(
  605. Device->UsbCoreHandle,
  606. 0,
  607. RTLW81_MAX_CONTROL_TRANSFER_SIZE,
  608. 0);
  609. if (Device->ControlTransfer == NULL) {
  610. Status = STATUS_INSUFFICIENT_RESOURCES;
  611. goto InitializeDeviceStructuresEnd;
  612. }
  613. Device->ControlTransfer->Buffer = VirtualAddress;
  614. Device->ControlTransfer->BufferPhysicalAddress = PhysicalAddress;
  615. Device->ControlTransfer->BufferActualLength = MaxControlSize;
  616. VirtualAddress += MaxControlSize;
  617. PhysicalAddress += MaxControlSize;
  618. Status = STATUS_SUCCESS;
  619. InitializeDeviceStructuresEnd:
  620. if (!KSUCCESS(Status)) {
  621. if (Device != NULL) {
  622. Rtlw81pDeviceReleaseReference(Device);
  623. Device = NULL;
  624. }
  625. }
  626. *NewDevice = Device;
  627. return Status;
  628. }
  629. VOID
  630. Rtlw81pDestroyDeviceStructures (
  631. PRTLW81_DEVICE Device
  632. )
  633. /*++
  634. Routine Description:
  635. This routine destroys an RTLW81xx device structure.
  636. Arguments:
  637. Device - Supplies a pointer to the device.
  638. Return Value:
  639. None.
  640. --*/
  641. {
  642. ULONG Index;
  643. //
  644. // Destroy all the allocated transfers. For good measure, make sure they
  645. // are cancelled.
  646. //
  647. for (Index = 0; Index < RTLW81_BULK_IN_TRANSFER_COUNT; Index += 1) {
  648. if (Device->BulkInTransfer[Index] != NULL) {
  649. UsbCancelTransfer(Device->BulkInTransfer[Index], TRUE);
  650. UsbDestroyTransfer(Device->BulkInTransfer[Index]);
  651. }
  652. }
  653. if (Device->ControlTransfer != NULL) {
  654. UsbCancelTransfer(Device->ControlTransfer, TRUE);
  655. UsbDestroyTransfer(Device->ControlTransfer);
  656. }
  657. if (Device->IoBuffer != NULL) {
  658. MmFreeIoBuffer(Device->IoBuffer);
  659. }
  660. //
  661. // There should be no active bulk out transfers, so destroy all the free
  662. // transfers.
  663. //
  664. Rtlw81pDestroyBulkOutTransfers(Device);
  665. if (Device->BulkOutListLock != NULL) {
  666. KeDestroyQueuedLock(Device->BulkOutListLock);
  667. }
  668. MmFreePagedPool(Device);
  669. return;
  670. }
  671. VOID
  672. Rtlw81pDeviceAddReference (
  673. PRTLW81_DEVICE Device
  674. )
  675. /*++
  676. Routine Description:
  677. This routine increments the reference count of the given RTLW81xx device.
  678. Arguments:
  679. Device - Supplies a pointer to the SM95 device.
  680. Return Value:
  681. None.
  682. --*/
  683. {
  684. ULONG OldReferenceCount;
  685. OldReferenceCount = RtlAtomicAdd32(&(Device->ReferenceCount), 1);
  686. ASSERT((OldReferenceCount != 0) & (OldReferenceCount < 0x20000000));
  687. return;
  688. }
  689. VOID
  690. Rtlw81pDeviceReleaseReference (
  691. PRTLW81_DEVICE Device
  692. )
  693. /*++
  694. Routine Description:
  695. This routine decrements the reference count of the given RTLW81xx device.
  696. Arguments:
  697. Device - Supplies a pointer to the SM95 device.
  698. Return Value:
  699. None.
  700. --*/
  701. {
  702. ULONG OldReferenceCount;
  703. OldReferenceCount = RtlAtomicAdd32(&(Device->ReferenceCount), -1);
  704. ASSERT(OldReferenceCount != 0);
  705. if (OldReferenceCount == 1) {
  706. Rtlw81pDestroyDeviceStructures(Device);
  707. }
  708. return;
  709. }
  710. KSTATUS
  711. Rtlw81pSetUpUsbDevice (
  712. PRTLW81_DEVICE Device
  713. )
  714. /*++
  715. Routine Description:
  716. This routine claims the proper interface for the device and finds the
  717. bulk in, bulk out, and interrupt endpoints.
  718. Arguments:
  719. Device - Supplies a pointer to the device.
  720. Return Value:
  721. Status code.
  722. --*/
  723. {
  724. ULONG BulkOutEndpointCount;
  725. PUSB_CONFIGURATION_DESCRIPTION Configuration;
  726. PLIST_ENTRY CurrentEntry;
  727. USB_TRANSFER_DIRECTION Direction;
  728. PUSB_ENDPOINT_DESCRIPTION Endpoint;
  729. UCHAR EndpointType;
  730. ULONG Index;
  731. PUSB_INTERFACE_DESCRIPTION Interface;
  732. KSTATUS Status;
  733. if (Device->InterfaceClaimed != FALSE) {
  734. ASSERT((Device->BulkInEndpoint != 0) &&
  735. (Device->BulkOutEndpointCount != 0));
  736. Status = STATUS_SUCCESS;
  737. goto SetUpUsbDeviceEnd;
  738. }
  739. //
  740. // If the configuration isn't yet set, set the first one.
  741. //
  742. Configuration = UsbGetActiveConfiguration(Device->UsbCoreHandle);
  743. if (Configuration == NULL) {
  744. Status = UsbSetConfiguration(Device->UsbCoreHandle, 0, TRUE);
  745. if (!KSUCCESS(Status)) {
  746. goto SetUpUsbDeviceEnd;
  747. }
  748. Configuration = UsbGetActiveConfiguration(Device->UsbCoreHandle);
  749. ASSERT(Configuration != NULL);
  750. }
  751. //
  752. // Get and verify the interface.
  753. //
  754. Interface = UsbGetDesignatedInterface(Device->OsDevice,
  755. Device->UsbCoreHandle);
  756. if (Interface == NULL) {
  757. Status = STATUS_NO_INTERFACE;
  758. goto SetUpUsbDeviceEnd;
  759. }
  760. if (Interface->Descriptor.Class != UsbInterfaceClassVendor) {
  761. Status = STATUS_NO_INTERFACE;
  762. goto SetUpUsbDeviceEnd;
  763. }
  764. //
  765. // Locate the IN and OUT bulk endpoints, and the interrupt endpoint.
  766. //
  767. BulkOutEndpointCount = 0;
  768. CurrentEntry = Interface->EndpointListHead.Next;
  769. while (CurrentEntry != &(Interface->EndpointListHead)) {
  770. if ((Device->BulkInEndpoint != 0) &&
  771. (BulkOutEndpointCount == RTLW81_MAX_BULK_OUT_ENDPOINT_COUNT)) {
  772. break;
  773. }
  774. Endpoint = LIST_VALUE(CurrentEntry,
  775. USB_ENDPOINT_DESCRIPTION,
  776. ListEntry);
  777. CurrentEntry = CurrentEntry->Next;
  778. //
  779. // Deconstruct the components of the endpoint descriptor.
  780. //
  781. EndpointType = Endpoint->Descriptor.Attributes &
  782. USB_ENDPOINT_ATTRIBUTES_TYPE_MASK;
  783. if ((Endpoint->Descriptor.EndpointAddress &
  784. USB_ENDPOINT_ADDRESS_DIRECTION_IN) != 0) {
  785. Direction = UsbTransferDirectionIn;
  786. } else {
  787. Direction = UsbTransferDirectionOut;
  788. }
  789. //
  790. // Look to match the endpoint up to one of the required ones.
  791. //
  792. if (EndpointType == USB_ENDPOINT_ATTRIBUTES_TYPE_BULK) {
  793. if ((Device->BulkInEndpoint == 0) &&
  794. (Direction == UsbTransferDirectionIn)) {
  795. Device->BulkInEndpoint = Endpoint->Descriptor.EndpointAddress;
  796. } else if ((BulkOutEndpointCount <
  797. RTLW81_MAX_BULK_OUT_ENDPOINT_COUNT) &&
  798. (Direction == UsbTransferDirectionOut)) {
  799. Device->BulkOutEndpoint[BulkOutEndpointCount] =
  800. Endpoint->Descriptor.EndpointAddress;
  801. BulkOutEndpointCount += 1;
  802. }
  803. }
  804. }
  805. if ((Device->BulkInEndpoint == 0) ||
  806. (BulkOutEndpointCount == 0)) {
  807. Status = STATUS_INVALID_CONFIGURATION;
  808. goto SetUpUsbDeviceEnd;
  809. }
  810. //
  811. // Assign the bulk out endpoints based on how many there are.
  812. //
  813. if (BulkOutEndpointCount == 1) {
  814. for (Index = 0; Index < Rtlw81BulkOutTypeCount; Index += 1) {
  815. Device->BulkOutTypeEndpointIndex[Index] = 0;
  816. }
  817. } else if (BulkOutEndpointCount == 2) {
  818. Device->BulkOutTypeEndpointIndex[Rtlw81BulkOutBe] = 1;
  819. Device->BulkOutTypeEndpointIndex[Rtlw81BulkOutBk] = 1;
  820. Device->BulkOutTypeEndpointIndex[Rtlw81BulkOutVi] = 0;
  821. Device->BulkOutTypeEndpointIndex[Rtlw81BulkOutVo] = 0;
  822. } else {
  823. ASSERT(BulkOutEndpointCount == RTLW81_MAX_BULK_OUT_ENDPOINT_COUNT);
  824. Device->BulkOutTypeEndpointIndex[Rtlw81BulkOutBe] = 2;
  825. Device->BulkOutTypeEndpointIndex[Rtlw81BulkOutBk] = 2;
  826. Device->BulkOutTypeEndpointIndex[Rtlw81BulkOutVi] = 1;
  827. Device->BulkOutTypeEndpointIndex[Rtlw81BulkOutVo] = 0;
  828. }
  829. //
  830. // Everything's all ready, claim the interface.
  831. //
  832. Status = UsbClaimInterface(Device->UsbCoreHandle,
  833. Interface->Descriptor.InterfaceNumber);
  834. if (!KSUCCESS(Status)) {
  835. goto SetUpUsbDeviceEnd;
  836. }
  837. Device->InterfaceNumber = Interface->Descriptor.InterfaceNumber;
  838. Device->InterfaceClaimed = TRUE;
  839. Status = STATUS_SUCCESS;
  840. SetUpUsbDeviceEnd:
  841. return Status;
  842. }
  843. KSTATUS
  844. Rtlw81pStartDevice (
  845. PIRP Irp,
  846. PRTLW81_DEVICE Device
  847. )
  848. /*++
  849. Routine Description:
  850. This routine starts the SMSC95xx LAN device.
  851. Arguments:
  852. Irp - Supplies a pointer to the start IRP.
  853. Device - Supplies a pointer to the device information.
  854. Return Value:
  855. Status code.
  856. --*/
  857. {
  858. KSTATUS Status;
  859. //
  860. // Start up the controller.
  861. //
  862. Status = Rtlw81pInitialize(Device, Irp);
  863. if (!KSUCCESS(Status)) {
  864. goto StartDeviceEnd;
  865. }
  866. StartDeviceEnd:
  867. return Status;
  868. }
  869. KSTATUS
  870. Rtlw81pStopDevice (
  871. PIRP Irp,
  872. PRTLW81_DEVICE Device
  873. )
  874. /*++
  875. Routine Description:
  876. This routine stops the SMSC95xx LAN device.
  877. Arguments:
  878. Irp - Supplies a pointer to the removal IRP.
  879. Device - Supplies a pointer to the device information.
  880. Return Value:
  881. Status code.
  882. --*/
  883. {
  884. //
  885. // Detach the device from USB core. This will cancel all transfer attached
  886. // to the device, including the in-flight bulk out transfers that this
  887. // driver does not track.
  888. //
  889. if (Device->UsbCoreHandle != INVALID_HANDLE) {
  890. UsbDetachDevice(Device->UsbCoreHandle);
  891. }
  892. if (Device->InterfaceClaimed != FALSE) {
  893. UsbReleaseInterface(Device->UsbCoreHandle, Device->InterfaceNumber);
  894. }
  895. if (Device->UsbCoreHandle != INVALID_HANDLE) {
  896. UsbDeviceClose(Device->UsbCoreHandle);
  897. }
  898. //
  899. // Remove the link from 802.11 core. It is no longer in service.
  900. //
  901. if (Device->Net80211Link != NULL) {
  902. Net80211RemoveLink(Device->Net80211Link);
  903. Device->Net80211Link = NULL;
  904. }
  905. Rtlw81pDeviceReleaseReference(Device);
  906. return STATUS_SUCCESS;
  907. }