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

2187 lines
62 KiB

4 years ago
  1. /****************************************************************************
  2. *
  3. * FTK_USER.C
  4. *
  5. * FastMAC Plus based NDIS3 miniport driver FTK interface. This module
  6. * contains all of the routines required to interface with the FastMAC
  7. * Plus FTK. This is includes the routines traditionally found in transmit.c
  8. * and receive.c.
  9. *
  10. * Copyright (c) Madge Networks Ltd 1994
  11. *
  12. * COMPANY CONFIDENTIAL
  13. *
  14. * Created: PBA 21/06/1994
  15. *
  16. ****************************************************************************/
  17. #include <ndis.h>
  18. #include "ftk_defs.h"
  19. #include "ftk_extr.h"
  20. #include "ftk_intr.h"
  21. #include "mdgmport.upd"
  22. #include "ndismod.h"
  23. /*---------------------------------------------------------------------------
  24. |
  25. | LOCAL VARIABLES
  26. |
  27. ---------------------------------------------------------------------------*/
  28. //
  29. // To cut down on accesses to the slot structures on the card we keep
  30. // a host cache of various detaisl we need.
  31. //
  32. typedef struct
  33. {
  34. DWORD PhysicalAddress;
  35. PVOID VirtualAddress;
  36. }
  37. RX_SLOT_CACHE, *PRX_SLOT_CACHE;
  38. typedef struct
  39. {
  40. ULONG BufferSize;
  41. ULONG SharedMemoryAllocation;
  42. PVOID SharedMemoryVirtAddr;
  43. DWORD SharedMemoryPhysAddr;
  44. RX_SLOT_CACHE rx_slot_cache[FMPLUS_MAX_RX_SLOTS];
  45. UINT active_rx_slot; /* Used to count through the slot array */
  46. }
  47. RX_SLOT_MGMNT, *PRX_SLOT_MGMNT;
  48. typedef struct
  49. {
  50. DWORD PhysicalAddress;
  51. PVOID VirtualAddress;
  52. }
  53. TX_SLOT_CACHE, *PTX_SLOT_CACHE;
  54. typedef struct
  55. {
  56. ULONG BufferSize;
  57. ULONG SharedMemoryAllocation;
  58. PVOID SharedMemoryVirtAddr;
  59. DWORD SharedMemoryPhysAddr;
  60. TX_SLOT_CACHE tx_slot_cache[FMPLUS_MAX_TX_SLOTS];
  61. UINT active_tx_slot;
  62. UINT first_tx_in_use;
  63. UINT number_tx_in_use;
  64. }
  65. TX_SLOT_MGMNT, *PTX_SLOT_MGMNT;
  66. #define FRAME_TYPE_MASK ((BYTE) 0xC0) // What is ANDed with FC byte.
  67. #define FRAME_TYPE_MAC ((BYTE) 0x00) // What's left for a MAC frame.
  68. typedef struct
  69. {
  70. ADAPTER_HANDLE adapter_handle;
  71. ADAPTER * adapter;
  72. TX_SLOT * tx_slot_ptr;
  73. RX_SLOT * rx_slot_ptr;
  74. UINT frame_length;
  75. UINT result1;
  76. UINT result2;
  77. }
  78. MPSAFE_INFO;
  79. #if 0
  80. typedef struct
  81. {
  82. ADAPTER_HANDLE handle;
  83. WORD location;
  84. WORD result;
  85. }
  86. RDIO;
  87. WORD
  88. _madge_rdio(
  89. void * ptr
  90. )
  91. {
  92. RDIO * rdio;
  93. rdio = (RDIO *) ptr;
  94. sys_outsw(
  95. rdio->handle,
  96. adapter_record[rdio->handle]->sif_adr,
  97. rdio->location
  98. );
  99. rdio->result = sys_insw(
  100. rdio->handle,
  101. adapter_record[rdio->handle]->sif_dat
  102. );
  103. return 0;
  104. }
  105. WORD
  106. madge_rdio(
  107. ADAPTER_HANDLE adapter_handle,
  108. WORD dio_location
  109. )
  110. {
  111. RDIO rdio;
  112. rdio.handle = adapter_handle;
  113. rdio.location = dio_location;
  114. sys_sync_with_interrupt(
  115. adapter_handle,
  116. _madge_rdio,
  117. (void *) &rdio
  118. );
  119. return rdio.result;
  120. }
  121. void
  122. madge_dump_fmplus_info(
  123. ADAPTER_HANDLE adapter_handle
  124. )
  125. {
  126. ADAPTER * adapter;
  127. PRX_SLOT_MGMNT rx_slot_mgmnt;
  128. PTX_SLOT_MGMNT tx_slot_mgmnt;
  129. PMADGE_ADAPTER ndisAdap;
  130. RX_SLOT * * rx_slot_array;
  131. TX_SLOT * * tx_slot_array;
  132. UINT active_rx_slot;
  133. UINT active_tx_slot;
  134. UINT first_tx_slot;
  135. UINT rx_slots;
  136. UINT tx_slots;
  137. UINT i;
  138. adapter = adapter_record[adapter_handle];
  139. rx_slot_array = adapter->rx_slot_array;
  140. rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
  141. active_rx_slot = rx_slot_mgmnt->active_rx_slot;
  142. rx_slots = adapter->init_block->fastmac_parms.rx_slots;
  143. tx_slot_array = adapter->tx_slot_array;
  144. tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
  145. active_tx_slot = tx_slot_mgmnt->active_tx_slot;
  146. first_tx_slot = tx_slot_mgmnt->first_tx_in_use;
  147. tx_slots = adapter->init_block->fastmac_parms.tx_slots;
  148. DbgPrint("----------------------------------------------------------\n");
  149. DbgPrint(
  150. "SIFADR high word = %04x\n\n",
  151. sys_insw(adapter_handle, adapter->sif_adx)
  152. );
  153. DbgPrint("RX SLOTS:\n\n");
  154. DbgPrint("Active slot = %d\n", active_rx_slot);
  155. DbgPrint(" Len Res Buffer Stat Next\n");
  156. DbgPrint(" ---- ---- --------- ---- ----\n");
  157. for (i = 0; i < rx_slots; i++)
  158. {
  159. DbgPrint(
  160. "%04x: %04x %04x %04x %04x %04x %04x\n",
  161. (WORD) (card_t) rx_slot_array[i],
  162. madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->buffer_len),
  163. madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->reserved),
  164. madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->buffer_hiw),
  165. madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->buffer_low),
  166. madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->rx_status),
  167. madge_rdio(adapter_handle, (WORD) (card_t) &rx_slot_array[i]->next_slot)
  168. );
  169. }
  170. DbgPrint("\n");
  171. DbgPrint("TX SLOTS:\n\n");
  172. DbgPrint("Active slot = %d\n", active_tx_slot);
  173. DbgPrint("First used slot = %d\n", first_tx_slot);
  174. DbgPrint(" Stat SLen LLen Res1 Res2 Sbuffer Next LBuffer\n");
  175. DbgPrint(" ---- ---- ---- ---- ---- --------- ---- ---------\n");
  176. for (i = 0; i < tx_slots; i++)
  177. {
  178. DbgPrint(
  179. "%04x: %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
  180. (WORD) (card_t) tx_slot_array[i],
  181. madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->tx_status),
  182. madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->small_buffer_len),
  183. madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->large_buffer_len),
  184. madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->reserved[0]),
  185. madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->reserved[1]),
  186. madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->small_buffer_hiw),
  187. madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->small_buffer_low),
  188. madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->next_slot),
  189. madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->large_buffer_hiw),
  190. madge_rdio(adapter_handle, (WORD) (card_t) &tx_slot_array[i]->large_buffer_low)
  191. );
  192. }
  193. DbgPrint("\n");
  194. DbgPrint("DIO LOCATION 0x0CE0\n\n");
  195. for (i = 0; i < 32; i++)
  196. {
  197. DbgPrint(" %04x", madge_rdio(adapter_handle, (WORD) (0x0ce0 + i * 2)));
  198. if (i == 15)
  199. {
  200. DbgPrint("\n");
  201. }
  202. }
  203. DbgPrint("\n");
  204. }
  205. #endif
  206. /***************************************************************************
  207. *
  208. * Function - rxtx_allocate_rx_buffers
  209. *
  210. * Parameters - adapter -> Pointer to an FTK adapter structure.
  211. * max_frame_size -> Maximum frame size.
  212. * number_of_slots -> Number of receive slots.
  213. *
  214. * Purpose - Allocate buffer space for the receive slots.
  215. *
  216. * Returns - TRUE if it succeeds or FALSE otherwise.
  217. *
  218. ****************************************************************************/
  219. WBOOLEAN
  220. rxtx_allocate_rx_buffers(
  221. ADAPTER * adapter,
  222. WORD max_frame_size,
  223. WORD number_of_slots
  224. );
  225. #pragma FTK_INIT_FUNCTION(rxtx_allocate_rx_buffers)
  226. WBOOLEAN
  227. rxtx_allocate_rx_buffers(
  228. ADAPTER * adapter,
  229. WORD max_frame_size,
  230. WORD number_of_slots
  231. )
  232. {
  233. PRX_SLOT_MGMNT rx_slot_mgmnt;
  234. NDIS_STATUS status;
  235. ADAPTER_HANDLE adapter_handle;
  236. PMADGE_ADAPTER ndisAdap;
  237. DWORD SharedMemVirtAddr;
  238. DWORD SharedMemPhysAddr;
  239. //
  240. // Pre-calculate some commonly used values.
  241. //
  242. rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
  243. //
  244. // Only want to allocate the receive buffers and slot management once
  245. // per adapter.
  246. //
  247. if (rx_slot_mgmnt == NULL)
  248. {
  249. //
  250. // Pre-calculate some commonly used values.
  251. //
  252. adapter_handle = adapter->adapter_handle;
  253. ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
  254. //
  255. // Allocate the slot management structure.
  256. //
  257. MADGE_ALLOC_MEMORY(
  258. &status,
  259. &adapter->rx_slot_mgmnt,
  260. sizeof(RX_SLOT_MGMNT)
  261. );
  262. if (status != NDIS_STATUS_SUCCESS)
  263. {
  264. return FALSE;
  265. }
  266. MADGE_ZERO_MEMORY(adapter->rx_slot_mgmnt, sizeof(RX_SLOT_MGMNT));
  267. rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
  268. //
  269. // Work out how big the buffer should be. Remember to add
  270. // four to the buffer allocation for the CRC. The addition
  271. // of 32 provides a little space between receive buffers
  272. // for those naughty transport protocols that read more
  273. // then the indicated lookahead.
  274. //
  275. rx_slot_mgmnt->BufferSize = (max_frame_size + 4 + 32 + 3) & ~3;
  276. rx_slot_mgmnt->SharedMemoryAllocation =
  277. rx_slot_mgmnt->BufferSize * number_of_slots;
  278. //
  279. // Allocate the buffer.
  280. //
  281. if (!sys_alloc_dma_phys_buffer(
  282. adapter_handle,
  283. rx_slot_mgmnt->SharedMemoryAllocation,
  284. &SharedMemPhysAddr,
  285. &SharedMemVirtAddr
  286. ))
  287. {
  288. return FALSE;
  289. }
  290. rx_slot_mgmnt->SharedMemoryVirtAddr = (VOID *) SharedMemVirtAddr;
  291. rx_slot_mgmnt->SharedMemoryPhysAddr = SharedMemPhysAddr;
  292. }
  293. return TRUE;
  294. }
  295. /***************************************************************************
  296. *
  297. * Function - rxtx_setup_rx_buffers
  298. *
  299. * Parameters - adapter -> Pointer to an FTK adapter structure.
  300. * physical_addresses -> Use physical addresses?
  301. * number_of_slots -> Number of receive slots.
  302. *
  303. * Purpose - Set up the adapter receive slots.
  304. *
  305. * Returns - TRUE if it succeeds or FALSE otherwise.
  306. *
  307. ****************************************************************************/
  308. void
  309. rxtx_setup_rx_buffers(
  310. ADAPTER * adapter,
  311. WBOOLEAN physical_addresses,
  312. WORD number_of_slots
  313. );
  314. #pragma FTK_INIT_FUNCTION(rxtx_setup_rx_buffers)
  315. void
  316. rxtx_setup_rx_buffers(
  317. ADAPTER * adapter,
  318. WBOOLEAN physical_addresses,
  319. WORD number_of_slots
  320. )
  321. {
  322. PRX_SLOT_MGMNT rx_slot_mgmnt;
  323. NDIS_STATUS status;
  324. ADAPTER_HANDLE adapter_handle;
  325. PMADGE_ADAPTER ndisAdap;
  326. PVOID SharedMemVirtAddr;
  327. DWORD SharedMemPhysAddr;
  328. PRX_SLOT_CACHE rx_slot_cache;
  329. RX_SLOT * * rx_slot_array;
  330. DWORD phys_addr;
  331. WORD slot_index;
  332. WORD sifadr;
  333. WORD sifdat;
  334. WORD sifdatinc;
  335. UINT buffer_size;
  336. //
  337. // Pre-calculate some commonly used values.
  338. //
  339. adapter_handle = adapter->adapter_handle;
  340. ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
  341. rx_slot_array = adapter->rx_slot_array;
  342. rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
  343. rx_slot_cache = rx_slot_mgmnt->rx_slot_cache;
  344. SharedMemVirtAddr = rx_slot_mgmnt->SharedMemoryVirtAddr;
  345. SharedMemPhysAddr = rx_slot_mgmnt->SharedMemoryPhysAddr;
  346. buffer_size = rx_slot_mgmnt->BufferSize;
  347. sifadr = adapter->sif_adr;
  348. sifdat = adapter->sif_dat;
  349. sifdatinc = adapter->sif_datinc;
  350. MadgePrint2("rxtx_setup_rx_buffers number_of_slots = %d\n", number_of_slots);
  351. MadgePrint2("rxtx_setup_rx_buffers buffer_size = %d\n", buffer_size);
  352. //
  353. // Work out the physical and virtual address of each buffer.
  354. //
  355. for (slot_index = 0; slot_index < number_of_slots; slot_index++)
  356. {
  357. rx_slot_cache[slot_index].VirtualAddress = SharedMemVirtAddr;
  358. (PUCHAR) SharedMemVirtAddr += buffer_size;
  359. rx_slot_cache[slot_index].PhysicalAddress = SharedMemPhysAddr;
  360. SharedMemPhysAddr += buffer_size;
  361. phys_addr = (physical_addresses)
  362. ? (DWORD) rx_slot_cache[slot_index].PhysicalAddress
  363. : (DWORD) rx_slot_cache[slot_index].VirtualAddress;
  364. //
  365. // Write the buffer locations into the slots.
  366. //
  367. sys_outsw(
  368. adapter_handle,
  369. sifadr,
  370. (WORD) (card_t) &rx_slot_array[slot_index]->buffer_hiw
  371. );
  372. sys_outsw(
  373. adapter_handle,
  374. sifdatinc,
  375. (WORD) (phys_addr >> 16)
  376. );
  377. sys_outsw(
  378. adapter_handle,
  379. sifdat,
  380. (WORD) (phys_addr & 0x0FFFF)
  381. );
  382. }
  383. ndisAdap->RxTxBufferState |= MADGE_RX_INITIALIZED;
  384. rx_slot_mgmnt->active_rx_slot = 0;
  385. }
  386. /***************************************************************************
  387. *
  388. * Function - rxtx_free_rx_buffers
  389. *
  390. * Parameters - adapter -> Pointer to an FTK adapter structure.
  391. * max_frame_size -> Maximum frame size.
  392. * number_of_slots -> Number of receive slots.
  393. *
  394. * Purpose - Free the previously allocated receive buffers.
  395. *
  396. * Returns - Nothing.
  397. *
  398. ****************************************************************************/
  399. void
  400. rxtx_free_rx_buffers(
  401. ADAPTER * adapter,
  402. WORD max_frame_size,
  403. WORD number_of_slots
  404. )
  405. {
  406. ADAPTER_HANDLE adapter_handle;
  407. PMADGE_ADAPTER ndisAdap;
  408. PRX_SLOT_MGMNT rx_slot_mgmnt;
  409. //
  410. // Pre-calculate some commonly used values.
  411. //
  412. adapter_handle = adapter->adapter_handle;
  413. ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
  414. rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
  415. //
  416. // If the slot management structure exists them free it
  417. // and the buffers.
  418. //
  419. if (rx_slot_mgmnt != NULL)
  420. {
  421. if (rx_slot_mgmnt->SharedMemoryVirtAddr != NULL)
  422. {
  423. sys_free_dma_phys_buffer(
  424. adapter_handle,
  425. rx_slot_mgmnt->SharedMemoryAllocation,
  426. (DWORD) rx_slot_mgmnt->SharedMemoryPhysAddr,
  427. (DWORD) rx_slot_mgmnt->SharedMemoryVirtAddr
  428. );
  429. }
  430. MADGE_FREE_MEMORY(adapter->rx_slot_mgmnt, sizeof(RX_SLOT_MGMNT));
  431. adapter->rx_slot_mgmnt = NULL;
  432. ndisAdap->RxTxBufferState &= ~MADGE_RX_INITIALIZED;
  433. }
  434. }
  435. /***************************************************************************
  436. *
  437. * Function - rxtx_allocate_tx_buffers
  438. *
  439. * Parameters - adapter -> Pointer to an FTK adapter structure.
  440. * max_frame_size -> Maximum frame size.
  441. * number_of_slots -> Number of transmit slots.
  442. *
  443. * Purpose - Allocate buffer space for the transmit slots.
  444. *
  445. * Returns - TRUE if it succeeds or FALSE otherwise.
  446. *
  447. ****************************************************************************/
  448. WBOOLEAN
  449. rxtx_allocate_tx_buffers(
  450. ADAPTER * adapter,
  451. WORD max_frame_size,
  452. WORD number_of_slots
  453. );
  454. #pragma FTK_INIT_FUNCTION(rxtx_allocate_tx_buffers)
  455. WBOOLEAN
  456. rxtx_allocate_tx_buffers(
  457. ADAPTER * adapter,
  458. WORD max_frame_size,
  459. WORD number_of_slots
  460. )
  461. {
  462. PTX_SLOT_MGMNT tx_slot_mgmnt;
  463. NDIS_STATUS status;
  464. ADAPTER_HANDLE adapter_handle;
  465. PMADGE_ADAPTER ndisAdap;
  466. DWORD SharedMemVirtAddr;
  467. DWORD SharedMemPhysAddr;
  468. //
  469. // Pre-calculate some commonly used values.
  470. //
  471. tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
  472. //
  473. // Only want to allocate the receive buffers and slot management once
  474. // per adapter.
  475. //
  476. if (tx_slot_mgmnt == NULL)
  477. {
  478. //
  479. // Pre-calculate some commonly used values.
  480. //
  481. adapter_handle = adapter->adapter_handle;
  482. ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
  483. //
  484. // Allocate the slot management structure.
  485. //
  486. MADGE_ALLOC_MEMORY(
  487. &status,
  488. &adapter->tx_slot_mgmnt,
  489. sizeof(TX_SLOT_MGMNT)
  490. );
  491. if (status != NDIS_STATUS_SUCCESS)
  492. {
  493. return FALSE;
  494. }
  495. MADGE_ZERO_MEMORY(adapter->tx_slot_mgmnt, sizeof(TX_SLOT_MGMNT));
  496. tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
  497. //
  498. // Work out how big the buffer should be.
  499. //
  500. tx_slot_mgmnt->BufferSize = (max_frame_size + 3) & ~3;
  501. tx_slot_mgmnt->SharedMemoryAllocation =
  502. tx_slot_mgmnt->BufferSize * number_of_slots;
  503. //
  504. // Allocate the buffer.
  505. //
  506. if (!sys_alloc_dma_phys_buffer(
  507. adapter_handle,
  508. tx_slot_mgmnt->SharedMemoryAllocation,
  509. &SharedMemPhysAddr,
  510. &SharedMemVirtAddr
  511. ))
  512. {
  513. return FALSE;
  514. }
  515. tx_slot_mgmnt->SharedMemoryVirtAddr = (VOID *) SharedMemVirtAddr;
  516. tx_slot_mgmnt->SharedMemoryPhysAddr = SharedMemPhysAddr;
  517. }
  518. return TRUE;
  519. }
  520. /***************************************************************************
  521. *
  522. * Function - rxtx_setup_tx_buffers
  523. *
  524. * Parameters - adapter -> Pointer to an FTK adapter structure.
  525. * physical_addresses -> Use physical addresses?
  526. * number_of_slots -> Number of transmit slots.
  527. *
  528. * Purpose - Set up the adapter transmit slots.
  529. *
  530. * Returns - TRUE if it succeeds or FALSE otherwise.
  531. *
  532. ****************************************************************************/
  533. void
  534. rxtx_setup_tx_buffers(
  535. ADAPTER * adapter,
  536. WBOOLEAN physical_addresses,
  537. WORD number_of_slots
  538. );
  539. #pragma FTK_INIT_FUNCTION(rxtx_setup_tx_buffers)
  540. void
  541. rxtx_setup_tx_buffers(
  542. ADAPTER * adapter,
  543. WBOOLEAN physical_addresses,
  544. WORD number_of_slots
  545. )
  546. {
  547. PTX_SLOT_MGMNT tx_slot_mgmnt;
  548. NDIS_STATUS status;
  549. ADAPTER_HANDLE adapter_handle;
  550. PMADGE_ADAPTER ndisAdap;
  551. PVOID SharedMemVirtAddr;
  552. DWORD SharedMemPhysAddr;
  553. PTX_SLOT_CACHE tx_slot_cache;
  554. TX_SLOT * * tx_slot_array;
  555. DWORD phys_addr;
  556. WORD slot_index;
  557. WORD sifadr;
  558. WORD sifdat;
  559. WORD sifdatinc;
  560. UINT buffer_size;
  561. //
  562. // Pre-calculate some commonly used values.
  563. //
  564. adapter_handle = adapter->adapter_handle;
  565. ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
  566. tx_slot_array = adapter->tx_slot_array;
  567. tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
  568. tx_slot_cache = tx_slot_mgmnt->tx_slot_cache;
  569. SharedMemVirtAddr = tx_slot_mgmnt->SharedMemoryVirtAddr;
  570. SharedMemPhysAddr = tx_slot_mgmnt->SharedMemoryPhysAddr;
  571. buffer_size = tx_slot_mgmnt->BufferSize;
  572. sifadr = adapter->sif_adr;
  573. sifdat = adapter->sif_dat;
  574. sifdatinc = adapter->sif_datinc;
  575. MadgePrint2("rxtx_setup_tx_buffers number_of_slots = %d\n", number_of_slots);
  576. MadgePrint2("rxtx_setup_tx_buffers buffer_size = %d\n", buffer_size);
  577. //
  578. // Work out the physical and virtual address of each buffer.
  579. //
  580. for (slot_index = 0; slot_index < number_of_slots; slot_index++)
  581. {
  582. tx_slot_cache[slot_index].VirtualAddress = SharedMemVirtAddr;
  583. (PUCHAR) SharedMemVirtAddr += buffer_size;
  584. tx_slot_cache[slot_index].PhysicalAddress = SharedMemPhysAddr;
  585. SharedMemPhysAddr += buffer_size;
  586. phys_addr = (physical_addresses)
  587. ? (DWORD) tx_slot_cache[slot_index].PhysicalAddress
  588. : (DWORD) tx_slot_cache[slot_index].VirtualAddress;
  589. //
  590. // Write the buffer locations into the slots.
  591. //
  592. sys_outsw(
  593. adapter_handle,
  594. sifadr,
  595. (WORD) (card_t) &tx_slot_array[slot_index]->large_buffer_hiw
  596. );
  597. sys_outsw(
  598. adapter_handle,
  599. sifdatinc,
  600. (WORD) (phys_addr >> 16)
  601. );
  602. sys_outsw(
  603. adapter_handle,
  604. sifdat,
  605. (WORD) (phys_addr & 0x0FFFF)
  606. );
  607. }
  608. ndisAdap->RxTxBufferState |= MADGE_TX_INITIALIZED;
  609. tx_slot_mgmnt->active_tx_slot = 0;
  610. tx_slot_mgmnt->first_tx_in_use = 0;
  611. tx_slot_mgmnt->number_tx_in_use = 0;
  612. }
  613. /***************************************************************************
  614. *
  615. * Function - rxtx_free_tx_buffers
  616. *
  617. * Parameters - adapter -> Pointer to an FTK adapter structure.
  618. * max_frame_size -> Maximum frame size.
  619. * number_of_slots -> Number of transmit slots.
  620. *
  621. * Purpose - Free the previously allocated transmit buffers.
  622. *
  623. * Returns - Nothing.
  624. *
  625. ****************************************************************************/
  626. void
  627. rxtx_free_tx_buffers(
  628. ADAPTER * adapter,
  629. WORD max_frame_size,
  630. WORD number_of_slots
  631. )
  632. {
  633. ADAPTER_HANDLE adapter_handle;
  634. PMADGE_ADAPTER ndisAdap;
  635. PTX_SLOT_MGMNT tx_slot_mgmnt;
  636. //
  637. // Pre-calculate some commonly used values.
  638. //
  639. adapter_handle = adapter->adapter_handle;
  640. ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
  641. tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
  642. //
  643. // If the slot management structure exists them free it
  644. // and the buffers.
  645. //
  646. if (tx_slot_mgmnt != NULL)
  647. {
  648. if (tx_slot_mgmnt->SharedMemoryVirtAddr != NULL)
  649. {
  650. sys_free_dma_phys_buffer(
  651. adapter_handle,
  652. tx_slot_mgmnt->SharedMemoryAllocation,
  653. (DWORD) tx_slot_mgmnt->SharedMemoryPhysAddr,
  654. (DWORD) tx_slot_mgmnt->SharedMemoryVirtAddr
  655. );
  656. }
  657. MADGE_FREE_MEMORY(adapter->tx_slot_mgmnt, sizeof(TX_SLOT_MGMNT));
  658. adapter->tx_slot_mgmnt = NULL;
  659. ndisAdap->RxTxBufferState &= ~MADGE_TX_INITIALIZED;
  660. }
  661. }
  662. /*--------------------------------------------------------------------------
  663. |
  664. | Function - MPSafeReadTxStatus
  665. |
  666. | Paramters - ptr -> Pointer to an MPSAFE_INFO structure.
  667. |
  668. | Purpose - Reads the transmit status from the next slot to use. This
  669. | function is called via NdisSynchronizeWithInterrupt when
  670. | in PIO mode so that we don't get SIF register contention
  671. | on a multiprocessor.
  672. |
  673. | Returns - Nothing.
  674. |
  675. --------------------------------------------------------------------------*/
  676. STATIC BOOLEAN
  677. MPSafeReadTxStatus(PVOID ptr)
  678. {
  679. MPSAFE_INFO * info = (MPSAFE_INFO *) ptr;
  680. //
  681. // Read the transmit status from the slot.
  682. //
  683. sys_outsw(
  684. info->adapter_handle,
  685. info->adapter->sif_adr,
  686. (WORD) (card_t) &(info->tx_slot_ptr)->tx_status
  687. );
  688. info->result1 = sys_insw(
  689. info->adapter_handle,
  690. info->adapter->sif_dat
  691. );
  692. return FALSE;
  693. }
  694. /***************************************************************************
  695. *
  696. * Function - rxtx_irq_tx_completion_check
  697. *
  698. * Parameters - adapter_handle -> FTK adapter handle.
  699. * adapter -> Pointer to FTK adapter structure.
  700. *
  701. * Purpose - Complete any outstanding transmits.
  702. *
  703. * Returns - Nothing.
  704. *
  705. ****************************************************************************/
  706. void
  707. rxtx_irq_tx_completion_check(
  708. ADAPTER_HANDLE adapter_handle,
  709. ADAPTER * adapter
  710. )
  711. {
  712. UINT tx_slots;
  713. PTX_SLOT_MGMNT tx_slot_mgmnt;
  714. PTX_SLOT_CACHE tx_slot_cache;
  715. TX_SLOT * * tx_slot_array;
  716. PMADGE_ADAPTER ndisAdap;
  717. UINT tx_status;
  718. MPSAFE_INFO info;
  719. WORD sifadr;
  720. WORD sifdat;
  721. //
  722. // Pre-calculate some commonly used values.
  723. //
  724. tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
  725. tx_slot_cache = tx_slot_mgmnt->tx_slot_cache;
  726. tx_slot_array = adapter->tx_slot_array;
  727. ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
  728. tx_slots = adapter->init_block->fastmac_parms.tx_slots;
  729. sifadr = adapter->sif_adr;
  730. sifdat = adapter->sif_dat;
  731. //
  732. // If we're doing multiprocessor safe PIO then we need to set up
  733. // the info structure.
  734. //
  735. if (ndisAdap->UseMPSafePIO)
  736. {
  737. info.adapter_handle = adapter_handle;
  738. info.adapter = adapter;
  739. }
  740. //
  741. // Iterate around the transmit slots that are are marked as in use
  742. // checking if they are now free. Note: we must work with the
  743. // global coopies of the first_tx_in_use and number_tx_in_use
  744. // in case rxtx_transmit_frame is called during our up-call
  745. // to the wrapper.
  746. //
  747. while (tx_slot_mgmnt->number_tx_in_use > 0)
  748. {
  749. //
  750. // Read the transmit status from the slot. If we're doing
  751. // multiprocessor safe PIO we must do the DIO via an ISR
  752. // synchronized function.
  753. //
  754. if (ndisAdap->UseMPSafePIO)
  755. {
  756. info.tx_slot_ptr = tx_slot_array[tx_slot_mgmnt->first_tx_in_use];
  757. NdisMSynchronizeWithInterrupt(
  758. &ndisAdap->Interrupt,
  759. MPSafeReadTxStatus,
  760. &info
  761. );
  762. tx_status = info.result1;
  763. }
  764. else
  765. {
  766. sys_outsw(
  767. adapter_handle,
  768. sifadr,
  769. (WORD) (card_t) &tx_slot_array[
  770. tx_slot_mgmnt->first_tx_in_use
  771. ]->tx_status
  772. );
  773. tx_status = sys_insw(
  774. adapter_handle,
  775. sifdat
  776. );
  777. }
  778. //
  779. // If the slot is still in use then we must give up. This will
  780. // also work if a PCMCIA adapter has been removed because
  781. // tx_status will have been read as 0xffff.
  782. //
  783. if (tx_status >= 0x8000 || tx_status == 0)
  784. {
  785. break;
  786. }
  787. //
  788. // Update the appropriate counters from the frame transmit
  789. // status.
  790. //
  791. if ((tx_status & TX_RECEIVE_STATUS_MASK) == TX_RECEIVE_LOST_FRAME)
  792. {
  793. ndisAdap->LostFrames++;
  794. }
  795. else if ((tx_status & GOOD_TX_FRAME_MASK) != GOOD_TX_FRAME_VALUE)
  796. {
  797. ndisAdap->FrameTransmitErrors++;
  798. }
  799. //
  800. // Update the slot usage.
  801. //
  802. tx_slot_mgmnt->number_tx_in_use--;
  803. if (++tx_slot_mgmnt->first_tx_in_use == tx_slots)
  804. {
  805. tx_slot_mgmnt->first_tx_in_use = 0;
  806. }
  807. //
  808. // Tell the wrapper that there is a free slot.
  809. //
  810. NdisMSendResourcesAvailable(ndisAdap->UsedInISR.MiniportHandle);
  811. }
  812. //
  813. // If there are any frames we have queued for transmit that
  814. // have not been completed then arm the timer so we are guaranteed
  815. // to be called again. Under normal operation our DPR gets called
  816. // often enough that this function is called frequently enough to
  817. // complete all of the frames. However if we have an adapter in a
  818. // fast bus (PCI/EISA) with a lot of RAM and we are not
  819. // getting any recieve interrupts we can occasionally miss
  820. // completing a frame. Hence the timer.
  821. //
  822. if (tx_slot_mgmnt->number_tx_in_use > 0)
  823. {
  824. NdisMSetTimer(&ndisAdap->CompletionTimer, 20);
  825. }
  826. }
  827. /*--------------------------------------------------------------------------
  828. |
  829. | Function - MPSafeStartTx
  830. |
  831. | Paramters - ptr -> Pointer to an MPSAFE_INFO structure.
  832. |
  833. | Purpose - Set up a tx slot and start the transmit going. This
  834. | function is called via NdisSynchronizeWithInterrupt when
  835. | in PIO mode so that we don't get SIF register contention
  836. | on a multiprocessor.
  837. |
  838. | Returns - Nothing.
  839. |
  840. --------------------------------------------------------------------------*/
  841. STATIC BOOLEAN
  842. MPSafeStartTx(PVOID ptr)
  843. {
  844. MPSAFE_INFO * info = (MPSAFE_INFO *) ptr;
  845. //
  846. // Reset the transmit status in the transmit slot.
  847. //
  848. sys_outsw(
  849. info->adapter_handle,
  850. info->adapter->sif_adr,
  851. (WORD) (card_t) &(info->tx_slot_ptr)->tx_status
  852. );
  853. sys_outsw(
  854. info->adapter_handle,
  855. info->adapter->sif_dat,
  856. 0x8000
  857. );
  858. //
  859. // Write in the length of the buffer into the transmit slot
  860. // (large buffer).
  861. //
  862. sys_outsw(
  863. info->adapter_handle,
  864. info->adapter->sif_adr,
  865. (WORD) (card_t) &(info->tx_slot_ptr)->large_buffer_len
  866. );
  867. sys_outsw(
  868. info->adapter_handle,
  869. info->adapter->sif_dat,
  870. (WORD) info->frame_length
  871. );
  872. //
  873. // Write the length of the small buffer in the transmit slot to
  874. // start the transmit going.
  875. //
  876. sys_outsw(
  877. info->adapter_handle,
  878. info->adapter->sif_adr,
  879. (WORD) (card_t) &(info->tx_slot_ptr)->small_buffer_len
  880. );
  881. sys_outsw(
  882. info->adapter_handle,
  883. info->adapter->sif_dat,
  884. FMPLUS_SBUFF_ZERO_LENGTH
  885. );
  886. return FALSE;
  887. }
  888. /***************************************************************************
  889. *
  890. * Function - rxtx_transmit_frame
  891. *
  892. * Parameters - adapter_handle -> FTK adapter handle.
  893. * tx_frame_identifier -> NDIS packet handle or a pointer
  894. * to some data to send.
  895. * tx_frame_length -> Length of the frame.
  896. * tx_is_packet -> TRUE if tx_frame_identifier is
  897. * an NDIS packet handle.
  898. *
  899. * Purpose - Attempts to transmit a frame by copying it into a transmit
  900. * buffer and activating a FastMAC Plus tx slot.
  901. *
  902. * Returns - DRIVER_TRANSMIT_SUCCESS if it succeeds or
  903. * DRIVER_TRANSMIT_FAILURE if it does not.
  904. *
  905. ****************************************************************************/
  906. WORD
  907. rxtx_transmit_frame(
  908. ADAPTER_HANDLE adapter_handle,
  909. DWORD tx_frame_identifier,
  910. WORD tx_frame_length,
  911. WORD tx_is_packet
  912. )
  913. {
  914. ADAPTER * adapter;
  915. PTX_SLOT_MGMNT tx_slot_mgmnt;
  916. PTX_SLOT_CACHE tx_slot_cache;
  917. TX_SLOT * tx_slot_ptr;
  918. UINT active_tx_slot;
  919. UINT tx_slots;
  920. PMADGE_ADAPTER ndisAdap;
  921. UINT bytes_copied;
  922. UINT tx_status;
  923. MPSAFE_INFO info;
  924. WORD sifadr;
  925. WORD sifdat;
  926. //
  927. // Pre-calculate some commonly used values.
  928. //
  929. adapter = adapter_record[adapter_handle];
  930. tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
  931. tx_slot_cache = tx_slot_mgmnt->tx_slot_cache;
  932. active_tx_slot = tx_slot_mgmnt->active_tx_slot;
  933. tx_slot_ptr = adapter->tx_slot_array[active_tx_slot];
  934. tx_slots = adapter->init_block->fastmac_parms.tx_slots;
  935. ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
  936. sifadr = adapter->sif_adr;
  937. sifdat = adapter->sif_dat;
  938. //
  939. // If we are a PCMCIA adapter it is possible that the adapter
  940. // may have been removed. To detect this we check if SIFADR
  941. // is 0xffff since this should not normally be true.
  942. //
  943. if (adapter->adapter_card_bus_type == ADAPTER_CARD_PCMCIA_BUS_TYPE)
  944. {
  945. if (sys_insw(adapter_handle, sifadr) == 0xffff)
  946. {
  947. rxtx_adapter_removed(adapter_handle);
  948. return DRIVER_TRANSMIT_SUCCEED;
  949. }
  950. }
  951. //
  952. // If the next slot to be used is still in use then we must
  953. // give up.
  954. //
  955. if (tx_slot_mgmnt->number_tx_in_use == tx_slots)
  956. {
  957. #ifdef OID_MADGE_MONITOR
  958. (ndisAdap->MonitorInfo).FailedToTransmit++;
  959. #endif
  960. return DRIVER_TRANSMIT_FAIL;
  961. }
  962. //
  963. // Copy the frame into the transmit buffer.
  964. //
  965. if (tx_is_packet)
  966. {
  967. MadgeCopyFromPacketToBuffer(
  968. (PNDIS_PACKET) tx_frame_identifier,
  969. 0,
  970. tx_frame_length,
  971. (PUCHAR) tx_slot_cache[active_tx_slot].VirtualAddress,
  972. &bytes_copied
  973. );
  974. }
  975. else
  976. {
  977. MADGE_MOVE_MEMORY(
  978. tx_slot_cache[active_tx_slot].VirtualAddress,
  979. (PUCHAR) tx_frame_identifier,
  980. tx_frame_length
  981. );
  982. }
  983. //
  984. // Set up the tx slot and start the transmit. If we're using
  985. // multiprocessor safe PIO then we must do the DIO via an ISR
  986. // synchronised function.
  987. //
  988. if (ndisAdap->UseMPSafePIO)
  989. {
  990. info.adapter_handle = adapter_handle;
  991. info.adapter = adapter;
  992. info.tx_slot_ptr = tx_slot_ptr;
  993. info.frame_length = tx_frame_length;
  994. NdisMSynchronizeWithInterrupt(
  995. &ndisAdap->Interrupt,
  996. MPSafeStartTx,
  997. &info
  998. );
  999. }
  1000. else
  1001. {
  1002. //
  1003. // Reset the transmit status in the transmit slot.
  1004. //
  1005. sys_outsw(
  1006. adapter_handle,
  1007. sifadr,
  1008. (WORD) (card_t) &tx_slot_ptr->tx_status
  1009. );
  1010. sys_outsw(
  1011. adapter_handle,
  1012. sifdat,
  1013. (WORD) 0x8000
  1014. );
  1015. //
  1016. // Write in the length of the buffer into the transmit slot
  1017. // (large buffer).
  1018. //
  1019. sys_outsw(
  1020. adapter_handle,
  1021. sifadr,
  1022. (WORD) (card_t) &tx_slot_ptr->large_buffer_len
  1023. );
  1024. sys_outsw(
  1025. adapter_handle,
  1026. sifdat,
  1027. (WORD) tx_frame_length
  1028. );
  1029. //
  1030. // Write the length of the small buffer in the transmit slot to
  1031. // start the transmit going.
  1032. //
  1033. sys_outsw(
  1034. adapter_handle,
  1035. sifadr,
  1036. (WORD) (card_t) &tx_slot_ptr->small_buffer_len
  1037. );
  1038. sys_outsw(
  1039. adapter_handle,
  1040. sifdat,
  1041. FMPLUS_SBUFF_ZERO_LENGTH
  1042. );
  1043. }
  1044. //
  1045. // Note that the slot is in use.
  1046. //
  1047. tx_slot_mgmnt->number_tx_in_use++;
  1048. //
  1049. // Update the slot counter ready for the next transmit.
  1050. //
  1051. if (++tx_slot_mgmnt->active_tx_slot == tx_slots)
  1052. {
  1053. tx_slot_mgmnt->active_tx_slot = 0;
  1054. }
  1055. return DRIVER_TRANSMIT_SUCCEED;
  1056. }
  1057. /*--------------------------------------------------------------------------
  1058. |
  1059. | Function - ProcessTestAndXIDFrames
  1060. |
  1061. | Paramters - adapHnd -> An FTK adapter handle.
  1062. | framePtr -> Pointer to the start of the frame.
  1063. | frameLen -> The length of the frame.
  1064. | headerLen -> The length of the frame header.
  1065. |
  1066. | Purpose - Process LLC Test and XID frames in the same way as IBM
  1067. | adapter hardware.
  1068. |
  1069. | Returns - TRUE if the frame was processed or FALSE if not.
  1070. |
  1071. |-------------------------------------------------------------------------*/
  1072. STATIC BOOLEAN
  1073. ProcessTestAndXIDFrames(
  1074. ADAPTER_HANDLE adapHnd,
  1075. UCHAR *framePtr,
  1076. UINT frameLen,
  1077. UINT headerLen
  1078. )
  1079. {
  1080. UINT llcCmd;
  1081. UINT sSAP;
  1082. NODE_ADDRESS tempNodeAddr;
  1083. BOOLEAN doneFrame;
  1084. doneFrame = FALSE;
  1085. //
  1086. // We are only interested in frames that are LLC (i.e. frame
  1087. // control byte is 0x40), have a null destination SAP and are
  1088. // commands (i.e. 0x01 bit of the source SAP is clear).
  1089. //
  1090. sSAP = framePtr[headerLen + 1];
  1091. if (framePtr[1] == 0x40 &&
  1092. framePtr[headerLen] == 0x00 &&
  1093. (sSAP & 0x01) == 0x00)
  1094. {
  1095. llcCmd = framePtr[headerLen + 2] & 0xef;
  1096. //
  1097. // Test frames have an LLC command byte of 0b111x0011.
  1098. //
  1099. if (llcCmd == 0xe3)
  1100. {
  1101. MadgePrint1("Got TEST frame\n");
  1102. //
  1103. // We don't need to do anything to a test frame
  1104. // other than send it back.
  1105. //
  1106. doneFrame = TRUE;
  1107. }
  1108. //
  1109. // XID frames have an LLC command byte of 0b101x1111 and
  1110. // a standard IEEE defined XID frame will have 3 data
  1111. // bytes and its first data byte set to 0x81.
  1112. //
  1113. else if (llcCmd == 0xaf &&
  1114. frameLen == headerLen + 6 &&
  1115. framePtr[headerLen + 3] == 0x81)
  1116. {
  1117. MadgePrint1("Got XID frame\n");
  1118. //
  1119. // Fill in the XID frame data with 0x81 0x01 0x00
  1120. // (Standard XID frame, type 1 only and 0 sized
  1121. // receive window).
  1122. //
  1123. framePtr[headerLen + 4] = 0x01;
  1124. framePtr[headerLen + 5] = 0x00;
  1125. doneFrame = TRUE;
  1126. }
  1127. //
  1128. // If we've had a TEST or a XID frame then doneFrame will
  1129. // be TRUE and we should send a frame back.
  1130. //
  1131. if (doneFrame)
  1132. {
  1133. //
  1134. // Flip the direction bit in the source routing
  1135. // control word and switch the source routing flag
  1136. // from the source to destination address.
  1137. //
  1138. if ((framePtr[8] & 0x80) != 0)
  1139. {
  1140. framePtr[14] &= 0x1f; // Clear broadcast bits.
  1141. framePtr[15] ^= 0x80; // Flip direction bit.
  1142. framePtr[8] &= 0x7f; // Clear source routing bit.
  1143. framePtr[2] |= 0x80; // Set source routing bit.
  1144. }
  1145. //
  1146. // Swap the node addresses around.
  1147. //
  1148. tempNodeAddr = *((NODE_ADDRESS *) &framePtr[2]);
  1149. *((NODE_ADDRESS *) &framePtr[2]) = *((NODE_ADDRESS *) &framePtr[8]);
  1150. *((NODE_ADDRESS *) &framePtr[8]) = tempNodeAddr;
  1151. //
  1152. // Swap the SAPs around and set the response bit in the
  1153. // new source SAP.
  1154. //
  1155. framePtr[headerLen + 1] = 0x01;
  1156. framePtr[headerLen] = sSAP;
  1157. framePtr[0] = 0x10;
  1158. //
  1159. // And now send the frame.
  1160. //
  1161. rxtx_transmit_frame(
  1162. adapHnd,
  1163. (DWORD) framePtr,
  1164. (WORD) frameLen,
  1165. FALSE
  1166. );
  1167. }
  1168. }
  1169. return doneFrame;
  1170. }
  1171. /*--------------------------------------------------------------------------
  1172. |
  1173. | Function - MPSafeReadRxStatus
  1174. |
  1175. | Paramters - ptr -> Pointer to an MPSAFE_INFO structure.
  1176. |
  1177. | Purpose - Read the status and length of the current rx slot. This
  1178. | function is called via NdisSynchronizeWithInterrupt when
  1179. | in PIO mode so that we don't get SIF register contention
  1180. | on a multiprocessor.
  1181. |
  1182. | Returns - Nothing.
  1183. |
  1184. --------------------------------------------------------------------------*/
  1185. STATIC BOOLEAN
  1186. MPSafeReadRxStatus(PVOID ptr)
  1187. {
  1188. MPSAFE_INFO * info = (MPSAFE_INFO *) ptr;
  1189. sys_outsw(
  1190. info->adapter_handle,
  1191. info->adapter->sif_adr,
  1192. (WORD) (card_t) &(info->rx_slot_ptr)->buffer_len
  1193. );
  1194. info->result1 = sys_insw(
  1195. info->adapter_handle,
  1196. info->adapter->sif_dat
  1197. );
  1198. sys_outsw(
  1199. info->adapter_handle,
  1200. info->adapter->sif_adr,
  1201. (WORD) (card_t) &(info->rx_slot_ptr)->rx_status
  1202. );
  1203. info->result2 = sys_insw(
  1204. info->adapter_handle,
  1205. info->adapter->sif_dat
  1206. );
  1207. return FALSE;
  1208. }
  1209. /*--------------------------------------------------------------------------
  1210. |
  1211. | Function - MPSafeFreeRxSlot
  1212. |
  1213. | Paramters - ptr -> Pointer to an MPSAFE_INFO structure.
  1214. |
  1215. | Purpose - Free an rx slot. This
  1216. | function is called via NdisSynchronizeWithInterrupt when
  1217. | in PIO mode so that we don't get SIF register contention
  1218. | on a multiprocessor.
  1219. |
  1220. | Returns - Nothing.
  1221. |
  1222. --------------------------------------------------------------------------*/
  1223. STATIC BOOLEAN
  1224. MPSafeFreeRxSlot(PVOID ptr)
  1225. {
  1226. MPSAFE_INFO * info = (MPSAFE_INFO *) ptr;
  1227. sys_outsw(
  1228. info->adapter_handle,
  1229. info->adapter->sif_adr,
  1230. (WORD) (card_t) &(info->rx_slot_ptr)->buffer_len
  1231. );
  1232. sys_outsw(
  1233. info->adapter_handle,
  1234. info->adapter->sif_dat,
  1235. (WORD) 0x0000
  1236. );
  1237. return FALSE;
  1238. }
  1239. /***************************************************************************
  1240. *
  1241. * Function - rxtx_irq_rx_frame_handler
  1242. *
  1243. * Parameters - adapter_handle -> FTK adapter handle.
  1244. * adapter -> Pointer to an FTK adapter structure.
  1245. *
  1246. * Purpose - Called out of the back or our DPR route via
  1247. * driver_get_outstanding_receive() to process received
  1248. * frames.
  1249. *
  1250. * Note we preserve the value of SIFADR so that the transmit
  1251. * code does not have to worry about it changing under its
  1252. * feet. No we don't because we are called out of a DPR
  1253. * and the wrapper will have grabbed a spin lock so
  1254. * we can't be executing at the same time as the transmit
  1255. * code.
  1256. *
  1257. * Returns - Nothing.
  1258. *
  1259. ****************************************************************************/
  1260. #define PROM_OR_MAC \
  1261. (NDIS_PACKET_TYPE_PROMISCUOUS | NDIS_PACKET_TYPE_MAC_FRAME)
  1262. void
  1263. rxtx_irq_rx_frame_handler(
  1264. ADAPTER_HANDLE adapter_handle,
  1265. ADAPTER * adapter
  1266. )
  1267. {
  1268. BYTE * rx_frame_addr;
  1269. UINT rx_frame_stat;
  1270. UINT rx_frame_length;
  1271. UINT slot_count;
  1272. UINT active_rx_slot;
  1273. PRX_SLOT_MGMNT rx_slot_mgmnt;
  1274. PRX_SLOT_CACHE rx_slot_cache;
  1275. RX_SLOT * * rx_slot_array;
  1276. RX_SLOT * rx_slot_ptr;
  1277. UINT rx_slots;
  1278. PMADGE_ADAPTER ndisAdap;
  1279. UINT packet_filter;
  1280. UINT header_len;
  1281. BOOLEAN done_frame;
  1282. BOOLEAN ignore_frame;
  1283. BOOLEAN test_and_xid;
  1284. MPSAFE_INFO info;
  1285. WORD sifadr;
  1286. WORD sifdat;
  1287. //
  1288. // Pre-calculate some commonly used values.
  1289. //
  1290. rx_slot_array = adapter->rx_slot_array;
  1291. rx_slot_mgmnt = (PRX_SLOT_MGMNT) adapter->rx_slot_mgmnt;
  1292. active_rx_slot = rx_slot_mgmnt->active_rx_slot;
  1293. rx_slot_cache = rx_slot_mgmnt->rx_slot_cache;
  1294. rx_slots = adapter->init_block->fastmac_parms.rx_slots;
  1295. ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
  1296. packet_filter = ndisAdap->CurrentPacketFilter;
  1297. test_and_xid = ndisAdap->TestAndXIDEnabled;
  1298. done_frame = FALSE;
  1299. sifadr = adapter->sif_adr;
  1300. sifdat = adapter->sif_dat;
  1301. //
  1302. // If we're doing multiprocessor safe PIO then we need to set up
  1303. // the info structure.
  1304. //
  1305. if (ndisAdap->UseMPSafePIO)
  1306. {
  1307. info.adapter_handle = adapter_handle;
  1308. info.adapter = adapter;
  1309. }
  1310. //
  1311. // Now read the length and status fields of the current receive slot.
  1312. // If we are doing multiprocessor safe PIO then we must do the DIO via
  1313. // an ISR synchronised function.
  1314. //
  1315. rx_slot_ptr = rx_slot_array[active_rx_slot];
  1316. if (ndisAdap->UseMPSafePIO)
  1317. {
  1318. info.rx_slot_ptr = rx_slot_ptr;
  1319. NdisMSynchronizeWithInterrupt(
  1320. &ndisAdap->Interrupt,
  1321. MPSafeReadRxStatus,
  1322. &info
  1323. );
  1324. rx_frame_length = info.result1;
  1325. rx_frame_stat = info.result2;
  1326. }
  1327. else
  1328. {
  1329. sys_outsw(
  1330. adapter_handle,
  1331. sifadr,
  1332. (WORD) (card_t) &rx_slot_ptr->buffer_len
  1333. );
  1334. rx_frame_length = sys_insw(
  1335. adapter_handle,
  1336. sifdat
  1337. );
  1338. sys_outsw(
  1339. adapter_handle,
  1340. sifadr,
  1341. (WORD) (card_t) &rx_slot_ptr->rx_status
  1342. );
  1343. rx_frame_stat = sys_insw(
  1344. adapter_handle,
  1345. sifdat
  1346. );
  1347. }
  1348. //
  1349. // Try to receive as many frames as possible, but only examine as many
  1350. // slots as we have, otherwise we might end up going round this loop
  1351. // forever! If we do stop and there is still a frame to be received, we
  1352. // will be re-interrupted anyway.
  1353. //
  1354. slot_count = 0;
  1355. while (rx_frame_length != 0 && slot_count++ < rx_slots)
  1356. {
  1357. //
  1358. // It is possible that a PCMCIA adapter may have been removed
  1359. // in which case we must not wait forever. If an adapter has
  1360. // been removed we would expect to read 0xffff from any IO
  1361. // location occupied by the adapter. 0xffff is not a valid
  1362. // value for an FMP RX status.
  1363. //
  1364. if (rx_frame_stat == 0xffff)
  1365. {
  1366. MadgePrint1("Rx frame: RX status == 0xffff\n");
  1367. ndisAdap->AdapterRemoved = TRUE;
  1368. return;
  1369. }
  1370. //
  1371. // FastMAC Plus includes the CRC in the frame length.
  1372. //
  1373. rx_frame_length -= 4;
  1374. if ((rx_frame_stat & GOOD_RX_FRAME_MASK) == 0)
  1375. {
  1376. //
  1377. // We have got a good frame here.
  1378. //
  1379. rx_frame_addr = rx_slot_cache[active_rx_slot].VirtualAddress;
  1380. header_len = (FRAME_IS_SOURCE_ROUTED(rx_frame_addr))
  1381. ? FRAME_HEADER_SIZE + FRAME_SOURCE_ROUTING_BYTES(rx_frame_addr)
  1382. : FRAME_HEADER_SIZE;
  1383. //
  1384. // Check for a frame copied error.
  1385. //
  1386. if ((rx_frame_addr[2] & 0x80) && (rx_frame_stat & 0x80))
  1387. {
  1388. ndisAdap->FrameCopiedErrors++;
  1389. }
  1390. //
  1391. // We may have to behave like the hardware of an IBM adapter
  1392. // and process LLC TEST and XID frames ourselves.
  1393. //
  1394. if (test_and_xid)
  1395. {
  1396. ignore_frame = ProcessTestAndXIDFrames(
  1397. adapter_handle,
  1398. rx_frame_addr,
  1399. rx_frame_length,
  1400. header_len
  1401. );
  1402. }
  1403. else
  1404. {
  1405. ignore_frame = FALSE;
  1406. }
  1407. //
  1408. // If we've got a valid frame then pass it up to the user.
  1409. //
  1410. if (!ignore_frame &&
  1411. ((rx_frame_addr[1] & FRAME_TYPE_MASK) != FRAME_TYPE_MAC ||
  1412. (packet_filter & PROM_OR_MAC) != 0))
  1413. {
  1414. //
  1415. // When indicating the frame, we can pass all of it
  1416. // as lookahead if we want, but we ought to take
  1417. // account of the current lookahead setting in case it
  1418. // is less than the frame size. This becomes important in
  1419. // WFWG, where it is unable to cope with large lookaheads. The
  1420. // lookahead length used to be :
  1421. // (UINT) rx_frame_length - header_len
  1422. //
  1423. NdisMTrIndicateReceive(
  1424. ndisAdap->UsedInISR.MiniportHandle,
  1425. (NDIS_HANDLE) (rx_frame_addr + header_len),
  1426. (PVOID) rx_frame_addr,
  1427. (UINT) header_len,
  1428. (PVOID) (rx_frame_addr + header_len),
  1429. (UINT) MIN(
  1430. ndisAdap->CurrentLookahead,
  1431. (rx_frame_length - header_len)
  1432. ),
  1433. (UINT) (rx_frame_length - header_len)
  1434. );
  1435. //
  1436. // Note that we've given the upper protocol at
  1437. // least one frame.
  1438. //
  1439. done_frame = TRUE;
  1440. ndisAdap->FramesReceived++;
  1441. #ifdef OID_MADGE_MONITOR
  1442. //
  1443. // Update the appropriate parts of the monitor structure
  1444. //
  1445. (ndisAdap->MonitorInfo).ReceiveFrames++;
  1446. (ndisAdap->MonitorInfo).ReceiveFrameSize[rx_frame_length/128]++;
  1447. (ndisAdap->MonitorInfo).CurrentFrameSize = rx_frame_length;
  1448. (ndisAdap->MonitorInfo).ReceiveFlag = 1;
  1449. #endif
  1450. }
  1451. }
  1452. //
  1453. // Otherwise we have some sort of receive error.
  1454. //
  1455. else
  1456. {
  1457. ndisAdap->FrameReceiveErrors++;
  1458. }
  1459. //
  1460. // Zero the frame length so that FastMAC Plus can reuse the buffer.
  1461. // If we're doing multiprocessor safe PIO then we must do the DIO
  1462. // via an ISR synchronised function.
  1463. //
  1464. if (ndisAdap->UseMPSafePIO)
  1465. {
  1466. info.rx_slot_ptr = rx_slot_ptr;
  1467. NdisMSynchronizeWithInterrupt(
  1468. &ndisAdap->Interrupt,
  1469. MPSafeFreeRxSlot,
  1470. &info
  1471. );
  1472. }
  1473. else
  1474. {
  1475. sys_outsw(
  1476. adapter_handle,
  1477. sifadr,
  1478. (WORD) (card_t) &rx_slot_ptr->buffer_len
  1479. );
  1480. sys_outsw(
  1481. adapter_handle,
  1482. sifdat,
  1483. 0x0000
  1484. );
  1485. }
  1486. //
  1487. // Update the active receive slot pointer.
  1488. //
  1489. if (++active_rx_slot == rx_slots)
  1490. {
  1491. active_rx_slot = 0;
  1492. }
  1493. rx_slot_mgmnt->active_rx_slot = active_rx_slot;
  1494. //
  1495. // Now we had better look at the next slot in case another frame
  1496. // has been received.
  1497. //
  1498. rx_slot_ptr = rx_slot_array[active_rx_slot];
  1499. if (ndisAdap->UseMPSafePIO)
  1500. {
  1501. info.rx_slot_ptr = rx_slot_ptr;
  1502. NdisMSynchronizeWithInterrupt(
  1503. &ndisAdap->Interrupt,
  1504. MPSafeReadRxStatus,
  1505. &info
  1506. );
  1507. rx_frame_length = info.result1;
  1508. rx_frame_stat = info.result2;
  1509. }
  1510. else
  1511. {
  1512. sys_outsw(
  1513. adapter_handle,
  1514. sifadr,
  1515. (WORD) (card_t) &rx_slot_ptr->buffer_len
  1516. );
  1517. rx_frame_length = sys_insw(
  1518. adapter_handle,
  1519. sifdat
  1520. );
  1521. sys_outsw(
  1522. adapter_handle,
  1523. sifadr,
  1524. (WORD) (card_t) &rx_slot_ptr->rx_status
  1525. );
  1526. rx_frame_stat = sys_insw(
  1527. adapter_handle,
  1528. sifdat
  1529. );
  1530. }
  1531. }
  1532. //
  1533. // If we've given the upper protocol a frame then call the
  1534. // receive completion routine.
  1535. //
  1536. if (done_frame)
  1537. {
  1538. NdisMTrIndicateReceiveComplete(ndisAdap->UsedInISR.MiniportHandle);
  1539. }
  1540. }
  1541. /***************************************************************************
  1542. *
  1543. * Function - rxtx_abort_txing_frames
  1544. *
  1545. * Parameters - adapter_handle -> FTK adapter handle.
  1546. *
  1547. * Purpose - Stop sending frames.
  1548. *
  1549. * Returns - Nothing.
  1550. *
  1551. ****************************************************************************/
  1552. void
  1553. rxtx_abort_txing_frames(ADAPTER_HANDLE adapter_handle)
  1554. {
  1555. //
  1556. // Nothing to do here.
  1557. //
  1558. }
  1559. /***************************************************************************
  1560. *
  1561. * Function - rxtx_await_empty_tx_slots
  1562. *
  1563. * Parameters - adapter_handle -> FTK adapter handle.
  1564. *
  1565. * Purpose - Wait until all of the tx slots are empty.
  1566. *
  1567. * Returns - Nothing.
  1568. *
  1569. ****************************************************************************/
  1570. void
  1571. rxtx_await_empty_tx_slots(ADAPTER_HANDLE adapter_handle)
  1572. {
  1573. ADAPTER * adapter;
  1574. FASTMAC_INIT_PARMS * fastmac_parms;
  1575. TX_SLOT * * tx_slot_array;
  1576. UINT i;
  1577. UINT status;
  1578. PMADGE_ADAPTER ndisAdap;
  1579. MPSAFE_INFO info;
  1580. WORD sifadr;
  1581. WORD sifdat;
  1582. if (!driver_check_adapter(adapter_handle, ADAPTER_RUNNING, SRB_ANY_STATE))
  1583. {
  1584. MadgePrint1("rxtx_await_empty_tx_slots: adapter not running\n");
  1585. return;
  1586. }
  1587. //
  1588. // Pre-calculate some commonly used values.
  1589. //
  1590. adapter = adapter_record[adapter_handle];
  1591. fastmac_parms = &adapter->init_block->fastmac_parms;
  1592. tx_slot_array = adapter->tx_slot_array;
  1593. info.adapter_handle = adapter_handle;
  1594. info.adapter = adapter;
  1595. ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
  1596. sifadr = adapter->sif_adr;
  1597. sifdat = adapter->sif_dat;
  1598. for (i = 0; i < fastmac_parms->tx_slots; i++)
  1599. {
  1600. do
  1601. {
  1602. //
  1603. // Get the slot status. If we are doing multiprocessor safe
  1604. // PIO then we must do this with an ISR synchronised function.
  1605. //
  1606. if (ndisAdap->UseMPSafePIO)
  1607. {
  1608. info.tx_slot_ptr = tx_slot_array[i];
  1609. NdisMSynchronizeWithInterrupt(
  1610. &ndisAdap->Interrupt,
  1611. MPSafeReadTxStatus,
  1612. &info
  1613. );
  1614. status = info.result1;
  1615. }
  1616. else
  1617. {
  1618. sys_outsw(
  1619. adapter_handle,
  1620. sifadr,
  1621. (WORD) (card_t) &tx_slot_array[i]->tx_status
  1622. );
  1623. status = sys_insw(adapter_handle, sifdat);
  1624. }
  1625. //
  1626. // It is possible that a PCMCIA adapter may have been removed
  1627. // in which case we must not wait forever. If an adapter has
  1628. // been removed we would expect to read 0xffff from any IO
  1629. // location occupied by the adapter. 0xffff is not a valid
  1630. // value for an FMP TX status.
  1631. //
  1632. if (status == 0xffff)
  1633. {
  1634. MadgePrint1("Await empty tx: TX status == 0xffff\n");
  1635. return;
  1636. }
  1637. }
  1638. while (status >= 0x8000 || status == 0);
  1639. }
  1640. }
  1641. /***************************************************************************
  1642. *
  1643. * Function - user_completed_srb
  1644. *
  1645. * Parameters - adapter_handle -> FTK adapter handle.
  1646. * srb_completed_successfully -> SRB successful?
  1647. *
  1648. * Purpose - Record that an SRB has completed and arrange for our
  1649. * DPR to be scheduled.
  1650. *
  1651. * Returns - Nothing.
  1652. *
  1653. ****************************************************************************/
  1654. void
  1655. user_completed_srb(
  1656. ADAPTER_HANDLE adapter_handle,
  1657. WBOOLEAN srb_completed_successfully
  1658. )
  1659. {
  1660. PMADGE_ADAPTER ndisAdap;
  1661. ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
  1662. //
  1663. // If we have issued a private SRB then we just clear the
  1664. // private SRB flag. Otherwise we need to arrange for our
  1665. // DPR to be told about the SRB.
  1666. //
  1667. if (ndisAdap->PrivateSrbInProgress)
  1668. {
  1669. ndisAdap->PrivateSrbInProgress = FALSE;
  1670. }
  1671. else
  1672. {
  1673. ndisAdap->UsedInISR.SrbRequestStatus = (BOOLEAN) srb_completed_successfully;
  1674. ndisAdap->UsedInISR.SrbRequestCompleted = TRUE;
  1675. ndisAdap->DprRequired = TRUE;
  1676. }
  1677. }
  1678. /***************************************************************************
  1679. *
  1680. * Function - user_shedule_receive_process
  1681. *
  1682. * Parameters - adapter_handle -> FTK adapter handle.
  1683. *
  1684. * Purpose - Arrange for our DPR to be scheduled so that we can deal
  1685. * with received frames.
  1686. *
  1687. * Returns - Nothing.
  1688. *
  1689. ****************************************************************************/
  1690. void
  1691. user_schedule_receive_process(ADAPTER_HANDLE adapter_handle)
  1692. {
  1693. PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle)->DprRequired = TRUE;
  1694. }
  1695. /***************************************************************************
  1696. *
  1697. * Function - user_adapter_removed
  1698. *
  1699. * Parameters - adapter_handle -> FTK adapter handle.
  1700. *
  1701. * Purpose - Arrange for our DPR to be scheduled so that we can deal
  1702. * with a removed adapter.
  1703. *
  1704. * Returns - Nothing.
  1705. *
  1706. ****************************************************************************/
  1707. void
  1708. user_adapter_removed(ADAPTER_HANDLE adapter_handle)
  1709. {
  1710. PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle)->DprRequired = TRUE;
  1711. PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle)->AdapterRemoved = TRUE;
  1712. }
  1713. /***************************************************************************
  1714. *
  1715. * Function - user_handle_adapter_check
  1716. *
  1717. * Parameters - adapter_handle -> FTK adapter handle.
  1718. *
  1719. * Purpose - Called on an adapter check. Not a lot we can do really!
  1720. *
  1721. * Returns - Nothing.
  1722. *
  1723. ****************************************************************************/
  1724. void
  1725. user_handle_adapter_check(ADAPTER_HANDLE adapter_handle)
  1726. {
  1727. MadgePrint1("Adapter Check!!!!\n");
  1728. }
  1729. //
  1730. // Currently we are not supporting transmit modes that require
  1731. // user completion routine.
  1732. //
  1733. #if 0
  1734. /***************************************************************************
  1735. *
  1736. * Function - user_transmit_completion
  1737. *
  1738. * Parameters - adapter_handle -> FTK adapter handle.
  1739. * identifier -> NDIS packet handle.
  1740. *
  1741. * Purpose - To notify an upper protocol that a transmit has completed.
  1742. *
  1743. * Returns - Nothing.
  1744. *
  1745. ****************************************************************************/
  1746. void
  1747. user_transmit_completion(
  1748. ADAPTER_HANDLE adapter_handle,
  1749. DWORD identifier
  1750. )
  1751. {
  1752. }
  1753. #endif
  1754. /***************************************************************************
  1755. *
  1756. * Function - rxtx_adapter_removed
  1757. *
  1758. * Parameters - adapter_handle -> FTK adapter handle.
  1759. *
  1760. * Purpose - Called to tidy up when we find out that the adapter has
  1761. * been removed. All we do is tell the wrapper that we
  1762. * have finished any submitted transmits.
  1763. *
  1764. * Returns - Nothing.
  1765. *
  1766. ****************************************************************************/
  1767. void
  1768. rxtx_adapter_removed(
  1769. ADAPTER_HANDLE adapter_handle
  1770. )
  1771. {
  1772. ADAPTER * adapter;
  1773. PTX_SLOT_MGMNT tx_slot_mgmnt;
  1774. UINT tx_slots;
  1775. PMADGE_ADAPTER ndisAdap;
  1776. //
  1777. // Pre-calculate some commonly used values.
  1778. //
  1779. adapter = adapter_record[adapter_handle];
  1780. tx_slot_mgmnt = (PTX_SLOT_MGMNT) adapter->tx_slot_mgmnt;
  1781. tx_slots = adapter->init_block->fastmac_parms.tx_slots;
  1782. ndisAdap = PMADGE_ADAPTER_FROM_ADAPTER_HANDLE(adapter_handle);
  1783. //
  1784. // Note that the adapter has been removed.
  1785. //
  1786. ndisAdap->AdapterRemoved = TRUE;
  1787. //
  1788. // Iterate around the transmit slots that are in use and
  1789. // up call to indicate that the transmits are over.
  1790. //
  1791. while (tx_slot_mgmnt->number_tx_in_use > 0)
  1792. {
  1793. //
  1794. // Update the slot usage.
  1795. //
  1796. tx_slot_mgmnt->number_tx_in_use--;
  1797. if (++tx_slot_mgmnt->first_tx_in_use == tx_slots)
  1798. {
  1799. tx_slot_mgmnt->first_tx_in_use = 0;
  1800. }
  1801. //
  1802. // Tell the wrapper that there is a free slot.
  1803. //
  1804. NdisMSendResourcesAvailable(ndisAdap->UsedInISR.MiniportHandle);
  1805. }
  1806. }
  1807. /******** End of FTK_USER.C ***********************************************/