Leaked source code of windows server 2003
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.

887 lines
28 KiB

  1. /*
  2. ************************************************************************
  3. *
  4. * NSCFIR.C
  5. *
  6. *
  7. * Portions Copyright (C) 1996-2001 National Semiconductor Corp.
  8. * All rights reserved.
  9. * Copyright (C) 1996-2001 Microsoft Corporation. All Rights Reserved.
  10. *
  11. *
  12. *
  13. *************************************************************************
  14. */
  15. #include "nsc.h"
  16. #include "nscfir.tmh"
  17. #include "nsctypes.h"
  18. VOID NSC_FIR_ISR(IrDevice *thisDev, BOOLEAN *claimingInterrupt,
  19. BOOLEAN *requireDeferredCallback)
  20. {
  21. LOG_FIR("==> NSC_FIR_ISR");
  22. DEBUGFIR(DBG_ISR|DBG_OUT, ("NSC: ==> NSC_FIR_ISR(0x%x)\n", thisDev));
  23. thisDev->InterruptMask = NSC_ReadBankReg(thisDev->portInfo.ioBase, 0, 1);
  24. thisDev->InterruptStatus = NSC_ReadBankReg(thisDev->portInfo.ioBase, 0, 2) & thisDev->FirIntMask;
  25. thisDev->AuxStatus = NSC_ReadBankReg(thisDev->portInfo.ioBase, 0, 7);
  26. thisDev->LineStatus = NSC_ReadBankReg(thisDev->portInfo.ioBase, 0, 5);
  27. LOG_FIR("InterruptMask: %02x, InterruptStatus: %02x", thisDev->InterruptMask,thisDev->InterruptStatus);
  28. LOG_FIR("AuxStatus: %02x, LineStatus: %02x", thisDev->AuxStatus,thisDev->LineStatus);
  29. DEBUGFIR(DBG_ISR|DBG_OUT, ("NSC: InterruptMask = 0x%x\n", thisDev->InterruptMask));
  30. DEBUGFIR(DBG_ISR|DBG_OUT, ("NSC: InterruptStatus = 0x%x\n", thisDev->InterruptStatus));
  31. DEBUGFIR(DBG_ISR|DBG_OUT, ("NSC: AuxStatus = 0x%x\n", thisDev->AuxStatus));
  32. DEBUGFIR(DBG_ISR|DBG_OUT, ("NSC: LineStatus = 0x%x\n", thisDev->LineStatus));
  33. if (thisDev->InterruptStatus) {
  34. //
  35. // After seeing the first packet switch the interrupt
  36. // to timer and use the DMA counter to decide if receptions
  37. // have stopped.
  38. //
  39. if (thisDev->InterruptStatus & LS_EV) {
  40. //
  41. // Got a link status interrupt
  42. //
  43. if (thisDev->LineStatus & LSR_FR_END) {
  44. //
  45. // The frame end status is set
  46. //
  47. if (!thisDev->FirTransmitPending) {
  48. //
  49. // we weren't tansmitting
  50. //
  51. }
  52. }
  53. if (thisDev->LineStatus & LSR_OE) {
  54. LOG_ERROR("NSC_FIR_ISR: rx overflow");
  55. }
  56. }
  57. if (thisDev->InterruptStatus & TMR_EV){
  58. //
  59. // Disable Timer during call to DPC bit.
  60. //
  61. NSC_WriteBankReg(thisDev->portInfo.ioBase, 4, 2, 0x00);
  62. NSC_WriteBankReg(thisDev->portInfo.ioBase, 0, 7, 0x80);
  63. }
  64. *claimingInterrupt = TRUE;
  65. *requireDeferredCallback = TRUE;
  66. SetCOMInterrupts(thisDev, FALSE);
  67. if (thisDev->UIR_ModuleId >= 0x16 )
  68. {
  69. // This is for the Frame stop mode when the ISR is interrupted
  70. // after every Frame Tx
  71. //
  72. if ((thisDev->AuxStatus & 0x08)
  73. && (thisDev->InterruptStatus & 0x04)
  74. && (thisDev->FirTransmitPending == TRUE))
  75. {
  76. if (thisDev->LineStatus&0x40)
  77. {
  78. NSC_WriteBankReg(thisDev->portInfo.ioBase, 0, 7, 0x40);
  79. DBGERR(("FIR: Transmit underrun\n"));
  80. }
  81. }
  82. }
  83. }
  84. else {
  85. *claimingInterrupt = FALSE;
  86. *requireDeferredCallback = FALSE;
  87. }
  88. LOG_FIR("<== NSC_FIR_ISR claimingInterrupt = %x, requireDeferredCallback = %x ", *claimingInterrupt,*requireDeferredCallback);
  89. DEBUGFIR(DBG_ISR|DBG_OUT, ("NSC: <== NSC_FIR_ISR\n"));
  90. }
  91. typedef struct {
  92. IrDevice *thisDev;
  93. ULONG_PTR Offset;
  94. ULONG_PTR Length;
  95. } DMASPACE;
  96. void SkipNonDmaBuffers(PLIST_ENTRY Head, PLIST_ENTRY *Entry)
  97. {
  98. while (Head!=*Entry)
  99. {
  100. rcvBuffer *rcvBuf = CONTAINING_RECORD(*Entry,
  101. rcvBuffer,
  102. listEntry);
  103. if (rcvBuf->isDmaBuf)
  104. {
  105. break;
  106. }
  107. else
  108. {
  109. *Entry = (*Entry)->Flink;
  110. }
  111. }
  112. }
  113. //
  114. // We have two lists of buffers which occupy our DMA space. We
  115. // want to walk this list and find the largest space for putting
  116. // new packets.
  117. //
  118. rcvBuffer *GetNextPacket(DMASPACE *Space,
  119. PLIST_ENTRY *CurrFull,
  120. PLIST_ENTRY *CurrPend)
  121. {
  122. rcvBuffer *Result = NULL;
  123. SkipNonDmaBuffers(&Space->thisDev->rcvBufFull, CurrFull);
  124. SkipNonDmaBuffers(&Space->thisDev->rcvBufPend, CurrPend);
  125. if (*CurrFull==&Space->thisDev->rcvBufFull)
  126. {
  127. // Full list is finished.
  128. if (*CurrPend!=&Space->thisDev->rcvBufPend)
  129. {
  130. // Any entry on the pend list is valid. Take the
  131. // next one and advance the pointer.
  132. Result = CONTAINING_RECORD(*CurrPend,
  133. rcvBuffer,
  134. listEntry);
  135. *CurrPend = (*CurrPend)->Flink;
  136. }
  137. else
  138. {
  139. // Both lists are finished. We will return NULL.
  140. }
  141. }
  142. else
  143. {
  144. if (*CurrPend==&Space->thisDev->rcvBufPend)
  145. {
  146. // Pend list is finished. Take anything from the
  147. // Full list, advance the pointer.
  148. Result = CONTAINING_RECORD(*CurrFull,
  149. rcvBuffer,
  150. listEntry);
  151. *CurrFull = (*CurrFull)->Flink;
  152. }
  153. else
  154. {
  155. // Both list have valid entries. Compare the two and take the
  156. // one that appears in the buffer first.
  157. rcvBuffer *Full, *Pend;
  158. Full = CONTAINING_RECORD(*CurrFull,
  159. rcvBuffer,
  160. listEntry);
  161. Pend = CONTAINING_RECORD(*CurrPend,
  162. rcvBuffer,
  163. listEntry);
  164. if (Full->dataBuf < Pend->dataBuf)
  165. {
  166. // Full is the winner. Take it.
  167. Result = Full;
  168. *CurrFull = (*CurrFull)->Flink;
  169. }
  170. else
  171. {
  172. // Pend is the winner. Take it.
  173. Result = Pend;
  174. *CurrPend = (*CurrPend)->Flink;
  175. }
  176. }
  177. }
  178. if (Result)
  179. {
  180. ASSERT(Result->isDmaBuf);
  181. }
  182. return Result;
  183. }
  184. BOOLEAN SynchronizedFindLargestSpace(IN PVOID Context)
  185. {
  186. DMASPACE *Space = Context;
  187. IrDevice *thisDev = Space->thisDev;
  188. BOOLEAN Result;
  189. PLIST_ENTRY Full, Pend;
  190. rcvBuffer *Current = NULL;
  191. ASSERT(sizeof(ULONG)==sizeof(PVOID));
  192. if (IsListEmpty(&thisDev->rcvBufFull) && IsListEmpty(&thisDev->rcvBufPend))
  193. {
  194. Space->Offset = (ULONG_PTR)thisDev->dmaReadBuf;
  195. Space->Length = RCV_DMA_SIZE;
  196. }
  197. else
  198. {
  199. ULONG_PTR EndOfLast;
  200. ULONG_PTR ThisSpace;
  201. Full = thisDev->rcvBufFull.Flink;
  202. Pend = thisDev->rcvBufPend.Flink;
  203. Space->Length = 0;
  204. EndOfLast = Space->Offset = (ULONG_PTR)thisDev->dmaReadBuf;
  205. Current = GetNextPacket(Space, &Full, &Pend);
  206. while (Current)
  207. {
  208. // It's possible to get a packet that is from SIR. If so, skip it.
  209. if (Current->isDmaBuf)
  210. {
  211. ASSERT((ULONG_PTR)Current->dataBuf >= EndOfLast);
  212. ThisSpace = (ULONG_PTR)Current->dataBuf - EndOfLast;
  213. // ASSERT the pointer is actually in our DMA buffer.
  214. ASSERT(Current->dataBuf >= thisDev->dmaReadBuf ||
  215. Current->dataBuf < thisDev->dmaReadBuf+RCV_DMA_SIZE);
  216. if (ThisSpace > Space->Length)
  217. {
  218. Space->Offset = EndOfLast;
  219. Space->Length = ThisSpace;
  220. }
  221. EndOfLast = (ULONG_PTR)Current->dataBuf + Current->dataLen;
  222. }
  223. Current = GetNextPacket(Space, &Full, &Pend);
  224. }
  225. // Now we do one more calculation for the space after the end of the list.
  226. ThisSpace = (ULONG_PTR)thisDev->dmaReadBuf + RCV_DMA_SIZE - (ULONG_PTR)EndOfLast;
  227. if (ThisSpace > Space->Length)
  228. {
  229. Space->Offset = EndOfLast;
  230. Space->Length = ThisSpace;
  231. }
  232. // Round off to start DMA on 4 byte boundary
  233. Space->Length -= 4 - (Space->Offset & 3);
  234. Space->Offset = (Space->Offset+3) & (~3);
  235. }
  236. // We want space relative to start of buffer.
  237. Space->Offset -= (ULONG_PTR)thisDev->dmaReadBuf;
  238. Result = (Space->Length >= MAX_RCV_DATA_SIZE + FAST_IR_FCS_SIZE);
  239. if (!Result)
  240. {
  241. DEBUGFIR(DBG_ERR, ("NSC: ERROR: Not enough space to DMA full packet %x\n", thisDev));
  242. }
  243. return Result;
  244. }
  245. BOOLEAN FindLargestSpace(IN IrDevice *thisDev,
  246. OUT PULONG_PTR pOffset,
  247. OUT PULONG_PTR pLength)
  248. {
  249. DMASPACE Space;
  250. BOOLEAN Result;
  251. Space.Offset = 0;
  252. Space.Length = 0;
  253. Space.thisDev = thisDev;
  254. Result = NdisMSynchronizeWithInterrupt(
  255. &thisDev->interruptObj,
  256. SynchronizedFindLargestSpace,
  257. &Space
  258. );
  259. *pOffset = Space.Offset;
  260. *pLength = Space.Length;
  261. return Result;
  262. }
  263. void FIR_DeliverFrames(IrDevice *thisDev)
  264. {
  265. UCHAR frameStat;
  266. NDIS_STATUS stat;
  267. ULONG rcvFrameSize;
  268. PUCHAR NewFrame;
  269. UCHAR BytesInFifo=0;
  270. ULONG_PTR LastReadDMACount, EndOfData;
  271. BOOLEAN resetDma = FALSE, OverflowOccurred = FALSE;
  272. BOOLEAN Discarding = thisDev->DiscardNextPacketSet;
  273. const UINT fcsSize = ( thisDev->currentSpeed >= MIN_FIR_SPEED) ?
  274. FAST_IR_FCS_SIZE : MEDIUM_IR_FCS_SIZE;
  275. LOG("==> FIR_DeliverFrames, prev dma=%d",(ULONG)thisDev->LastReadDMACount);
  276. DEBUGFIR(DBG_RX|DBG_OUT, ("NSC: ==> FIR_DeliverFrames(0x%x)\n", thisDev));
  277. LastReadDMACount = NdisMReadDmaCounter(thisDev->DmaHandle);
  278. // Check for data received since the last time we were here.
  279. // We also check for data in fifo. If there is some, we wait, as long
  280. // as the DMA still has room to capture data.
  281. if (LastReadDMACount > 0) {
  282. //
  283. // we have not transfered all of the data possible into the recieve area.
  284. // See if we have read more since the last time we were here
  285. //
  286. if (((LastReadDMACount < thisDev->LastReadDMACount) || (BytesInFifo=SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 2, 7) & 0x3f))) {
  287. //
  288. // we transfered something since
  289. // the last interrupt or there are still bytes in the fifo, then set a timer
  290. //
  291. thisDev->LastReadDMACount = LastReadDMACount;
  292. //
  293. // Set Timer Enable bit for another Timeout.
  294. //
  295. thisDev->FirIntMask = 0x90;
  296. SyncWriteBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 4, 2, 0x01);
  297. LOG_FIR("<== FIR_DeliverFrames- Enable timer, fifo=%02x, LastDma=%d",BytesInFifo,(ULONG)LastReadDMACount);
  298. DEBUGFIR(DBG_RX|DBG_OUT, ("NSC: <== FIR_DeliverFrames\n"));
  299. return;
  300. }
  301. } else {
  302. //
  303. // The dma count has gone to zero so we have transfered all we possibly can,
  304. // see if any thing is left in the fifo
  305. //
  306. BytesInFifo=SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 2, 7) & 0x3f;
  307. LOG("Receive: dma transfer complete, bytes in fifo=%d",BytesInFifo);
  308. //
  309. // we are stopping because the dma buffer filled up, not because the
  310. // receiver was idle
  311. //
  312. thisDev->ForceTurnAroundTimeout=TRUE;
  313. }
  314. RegStats.RxDPC_Window++;
  315. //
  316. // stop the dma transfer, so the data in the buffer will be valid
  317. //
  318. stat=CompleteDmaTransferFromDevice(&thisDev->DmaUtil);
  319. //
  320. // see how was transfer now that we have stopped the dma
  321. //
  322. LastReadDMACount = NdisMReadDmaCounter(thisDev->DmaHandle);
  323. if (stat != NDIS_STATUS_SUCCESS) {
  324. DBGERR(("NdisMCompleteDmaTransfer failed: %d\n", stat));
  325. ASSERT(0);
  326. //
  327. // could not complete the DMA, make it appear that zero bytes were transfered
  328. //
  329. LastReadDMACount=thisDev->rcvDmaSize;
  330. }
  331. thisDev->FirReceiveDmaActive=FALSE;
  332. thisDev->DiscardNextPacketSet = FALSE;
  333. EndOfData = thisDev->rcvDmaOffset + (thisDev->rcvDmaSize - LastReadDMACount);
  334. LOG("Recieve: Total data transfered %d",(ULONG)(thisDev->rcvDmaSize - LastReadDMACount));
  335. SyncGetFifoStatus(
  336. &thisDev->interruptObj,
  337. thisDev->portInfo.ioBase,
  338. &frameStat,
  339. &rcvFrameSize
  340. );
  341. if (frameStat == 0) LOG_ERROR("Receive: no frames in fifo");
  342. LOG("frameStat: %x, size=%d ", (UINT) frameStat,rcvFrameSize);
  343. DEBUGFIR(DBG_RX|DBG_OUT, ("NSC: frameStat = %xh\n", (UINT) frameStat));
  344. while ((frameStat & 0x80) && thisDev->rcvPktOffset < EndOfData) {
  345. /*
  346. * This status byte is valid; see what else it says...
  347. * Also mask off indeterminate bit.
  348. */
  349. frameStat &= ~0xA0;
  350. /*
  351. * Whether the frame is good or bad, we must read the counter
  352. * FIFO to synchronize it with the frame status FIFO.
  353. */
  354. if (Discarding)
  355. {
  356. LOG_ERROR("receive error: disc stat=%02x, lost=%d\n",frameStat,rcvFrameSize);
  357. // Do nothing
  358. }
  359. else if (frameStat != 0) {
  360. /*
  361. * Some rcv error occurred. Reset DMA.
  362. */
  363. LOG_ERROR("Receive error: stat=%02x, lost=%d\n",frameStat,rcvFrameSize);
  364. DEBUGFIR(DBG_RX|DBG_ERR, ("NSC: RCV ERR: frameStat=%xh FrameSize=%d \n",
  365. (UINT)frameStat,rcvFrameSize));
  366. if (frameStat & 0x40) {
  367. if (frameStat & 0x01) {
  368. RegStats.StatusFIFOOverflows++;
  369. }
  370. if (frameStat & 0x02) {
  371. RegStats.ReceiveFIFOOverflows++;
  372. }
  373. RegStats.MissedPackets += rcvFrameSize;
  374. }
  375. else{
  376. if (frameStat & 0x01) {
  377. RegStats.StatusFIFOOverflows++;
  378. }
  379. if (frameStat & 0x02) {
  380. RegStats.ReceiveFIFOOverflows++;
  381. }
  382. if (frameStat & 0x04) {
  383. RegStats.ReceiveCRCErrors++;
  384. }
  385. if (frameStat & 0x08) {
  386. }
  387. if (frameStat & 0x10) {
  388. }
  389. LOG("Bytes Lost: %d",rcvFrameSize);
  390. ASSERT((thisDev->rcvPktOffset + rcvFrameSize)<= RCV_DMA_SIZE);
  391. /* Advance pointer past bad packet. */
  392. thisDev->rcvPktOffset += rcvFrameSize;
  393. }
  394. }
  395. else if (thisDev->rcvPktOffset + rcvFrameSize > EndOfData )
  396. {
  397. LOG_ERROR("Receive: Frame extends beyond where dma control wrote: offset=%x, Frame size=%x, EndOfData=%x",(ULONG)thisDev->rcvPktOffset,(ULONG)rcvFrameSize,(ULONG)EndOfData);
  398. DBGERR(("Packet won't fit in received data!\n"));
  399. DBGERR(("rcvPktOffset:%x rcvFrameSize:%x LastReadDmaCount:%x\n",
  400. thisDev->rcvPktOffset,
  401. rcvFrameSize,
  402. LastReadDMACount));
  403. DBGERR(("rcvDmaOffset:%x rcvDmaSize:%x EndOfData:%x\n",
  404. thisDev->rcvDmaOffset, thisDev->rcvDmaSize, EndOfData));
  405. //
  406. // The frame seems to have extended past the end of where we dma the data.
  407. // This should only happen if the dma space just less than the size of
  408. // the fifo too small. The remaining data is still sitting in the fifo
  409. // Attempt to read it out so it will be empty when we got read more frames
  410. //
  411. while (BytesInFifo > 0) {
  412. SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, BANK_0, TXD_RXD_OFFSET);
  413. BytesInFifo--;
  414. }
  415. BytesInFifo=SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 2, 7) & 0x3f;
  416. if (BytesInFifo > 0) {
  417. //
  418. // still bytes in the fifo after attmpting to read them out.
  419. // Another frame has probably started showing up, Can trust the data collected
  420. // so mark these frames to be discarded
  421. //
  422. LOG_ERROR("Receive: Still have bytes in the fifo after attempting to flush, %d bytes remaining",BytesInFifo);
  423. BytesInFifo=0;
  424. thisDev->DiscardNextPacketSet = TRUE;
  425. }
  426. //
  427. // this should be the last frame to be received with out error, advance this pointer
  428. // anyway.
  429. //
  430. thisDev->rcvPktOffset += rcvFrameSize;
  431. }
  432. else {
  433. DEBUGFIR(DBG_RX|DBG_OUT, ("NSC: *** >>> FIR_DeliverFrames DMA offset 0x%x:\n",
  434. thisDev->rcvDmaOffset));
  435. //
  436. // this is where the new frame starts
  437. //
  438. NewFrame = thisDev->dmaReadBuf + thisDev->rcvPktOffset;
  439. //
  440. // the next frame will start after the end of this frame
  441. //
  442. thisDev->rcvPktOffset += rcvFrameSize;
  443. ASSERT(thisDev->rcvPktOffset < RCV_DMA_SIZE);
  444. //
  445. // the FCS is included in the length of the frame, remove that from the length
  446. // we send to the protocol
  447. //
  448. rcvFrameSize -= fcsSize;
  449. if (rcvFrameSize <= MAX_NDIS_DATA_SIZE &&
  450. rcvFrameSize >= IR_ADDR_SIZE + IR_CONTROL_SIZE)
  451. {
  452. //
  453. // Queue this rcv packet. Move Newframe pointer
  454. // into RxDMA buffer.
  455. //
  456. RegStats.ReceivedPackets++;
  457. RegStats.RxWindow++;
  458. QueueReceivePacket(thisDev, NewFrame, rcvFrameSize, TRUE);
  459. }
  460. else {
  461. LOG("Error: invalid packet size in FIR_DeliverFrames %d", rcvFrameSize);
  462. DEBUGFIR(DBG_RX|DBG_ERR, ("NSC: invalid packet size in FIR_DeliverFrames; %xh > %xh\n", rcvFrameSize, MAX_RCV_DATA_SIZE));
  463. //
  464. // Discard the rest of the packets.
  465. //
  466. while (SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 5, 5)&0x80)
  467. {
  468. SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 5, 6);
  469. SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 5, 7);
  470. }
  471. thisDev->DiscardNextPacketSet = TRUE;
  472. }
  473. }
  474. SyncGetFifoStatus(
  475. &thisDev->interruptObj,
  476. thisDev->portInfo.ioBase,
  477. &frameStat,
  478. &rcvFrameSize
  479. );
  480. LOG("frameStat: %x, size=%d ", (UINT) frameStat,rcvFrameSize);
  481. DEBUGFIR(DBG_RX|DBG_OUT, ("NSC: frameStat = %xh\n", (UINT) frameStat));
  482. //
  483. // Clear the line status register, of any past events.
  484. //
  485. thisDev->LineStatus = SyncReadBankReg(&thisDev->interruptObj,thisDev->portInfo.ioBase, 0, 5);
  486. }
  487. thisDev->FirIntMask = 0x04;
  488. SetupRecv(thisDev);
  489. LOG("<== FIR_DeliverFrames");
  490. DEBUGFIR(DBG_RX|DBG_OUT, ("NSC: <== FIR_DeliverFrames\n"));
  491. }
  492. BOOLEAN NSC_Setup(IrDevice *thisDev)
  493. {
  494. NDIS_DMA_DESCRIPTION DMAChannelDcr;
  495. NDIS_STATUS stat;
  496. /*
  497. * Initialize rcv DMA channel
  498. */
  499. RtlZeroMemory(&DMAChannelDcr,sizeof(DMAChannelDcr));
  500. DMAChannelDcr.DemandMode = TRUE;
  501. DMAChannelDcr.AutoInitialize = FALSE;
  502. DMAChannelDcr.DmaChannelSpecified = FALSE;
  503. DMAChannelDcr.DmaWidth = Width8Bits;
  504. DMAChannelDcr.DmaSpeed = Compatible;
  505. DMAChannelDcr.DmaPort = 0;
  506. DMAChannelDcr.DmaChannel = thisDev->portInfo.DMAChannel; // 0;
  507. stat = NdisMRegisterDmaChannel(&thisDev->DmaHandle,
  508. thisDev->ndisAdapterHandle,
  509. thisDev->portInfo.DMAChannel,
  510. FALSE, &DMAChannelDcr, RCV_DMA_SIZE);
  511. if (stat != NDIS_STATUS_SUCCESS) {
  512. DEBUGFIR(DBG_ERR, ("NSC: NdisMRegisterDmaChannel failed\n"));
  513. return FALSE;
  514. }
  515. InitializeDmaUtil(
  516. &thisDev->DmaUtil,
  517. thisDev->DmaHandle
  518. );
  519. thisDev->rcvDmaOffset = 0;
  520. /*
  521. * Because we enable rcv DMA while SIR receives may still be
  522. * going on, we need to keep a separate receive buffer for DMA.
  523. * This buffer gets swapped with the rcvBuffer data pointer
  524. * and must be the same size.
  525. */
  526. thisDev->dmaReadBuf=NscAllocateDmaBuffer(
  527. thisDev->ndisAdapterHandle,
  528. RCV_DMA_SIZE,
  529. &thisDev->ReceiveDmaBufferInfo
  530. );
  531. if (thisDev->dmaReadBuf == NULL) {
  532. return FALSE;
  533. }
  534. thisDev->TransmitDmaBuffer=NscAllocateDmaBuffer(
  535. thisDev->ndisAdapterHandle,
  536. MAX_IRDA_DATA_SIZE,
  537. &thisDev->TransmitDmaBufferInfo
  538. );
  539. NdisAllocateBufferPool(&stat, &thisDev->dmaBufferPoolHandle, 2);
  540. if (stat != NDIS_STATUS_SUCCESS){
  541. LOG("Error: NdisAllocateBufferPool failed in NSC_Setup");
  542. DEBUGFIR(DBG_ERR, ("NSC: NdisAllocateBufferPool failed in NSC_Setup\n"));
  543. return FALSE;
  544. }
  545. NdisAllocateBuffer(&stat, &thisDev->rcvDmaBuffer,
  546. thisDev->dmaBufferPoolHandle,
  547. thisDev->dmaReadBuf,
  548. RCV_DMA_SIZE
  549. );
  550. if (stat != NDIS_STATUS_SUCCESS) {
  551. LOG("Error: NdisAllocateBuffer failed (rcv) in NSC_Setup");
  552. DEBUGFIR(DBG_ERR, ("NSC: NdisAllocateBuffer failed (rcv) in NSC_Setup\n"));
  553. return FALSE;
  554. }
  555. NdisAllocateBuffer(&stat, &thisDev->xmitDmaBuffer,
  556. thisDev->dmaBufferPoolHandle,
  557. thisDev->TransmitDmaBuffer,
  558. MAX_IRDA_DATA_SIZE
  559. );
  560. if (stat != NDIS_STATUS_SUCCESS) {
  561. LOG("NdisAllocateBuffer failed (xmit) in NSC_Setup");
  562. DEBUGFIR(DBG_ERR, ("NSC: NdisAllocateBuffer failed (xmit) in NSC_Setup\n"));
  563. return FALSE;
  564. }
  565. return TRUE;
  566. }
  567. void NSC_Shutdown(IrDevice *thisDev)
  568. {
  569. if (thisDev->xmitDmaBuffer){
  570. NdisFreeBuffer( thisDev->xmitDmaBuffer);
  571. thisDev->xmitDmaBuffer = NULL;
  572. }
  573. if (thisDev->rcvDmaBuffer){
  574. NdisFreeBuffer(thisDev->rcvDmaBuffer);
  575. thisDev->rcvDmaBuffer = NULL;
  576. }
  577. if (thisDev->dmaBufferPoolHandle){
  578. NdisFreeBufferPool(thisDev->dmaBufferPoolHandle);
  579. thisDev->dmaBufferPoolHandle = NULL;
  580. }
  581. if (thisDev->dmaReadBuf){
  582. NscFreeDmaBuffer(&thisDev->ReceiveDmaBufferInfo);
  583. thisDev->dmaReadBuf = NULL;
  584. }
  585. if (thisDev->TransmitDmaBuffer){
  586. NscFreeDmaBuffer(&thisDev->TransmitDmaBufferInfo);
  587. thisDev->TransmitDmaBuffer = NULL;
  588. }
  589. if (thisDev->DmaHandle){
  590. NdisMDeregisterDmaChannel(thisDev->DmaHandle);
  591. thisDev->DmaHandle = NULL;
  592. }
  593. }
  594. BOOLEAN
  595. NdisToFirPacket(
  596. PNDIS_PACKET Packet,
  597. UCHAR *irPacketBuf,
  598. UINT TotalDmaBufferLength,
  599. UINT *ActualTransferLength
  600. )
  601. {
  602. PNDIS_BUFFER ndisBuf;
  603. UINT ndisPacketBytes = 0;
  604. UINT ndisPacketLen;
  605. LOG("==> NdisToFirPacket");
  606. DEBUGFIR(DBG_OUT, ("NSC: ==> NdisToFirPacket\n"));
  607. /*
  608. * Get the packet's entire length and its first NDIS buffer
  609. */
  610. NdisQueryPacket(Packet, NULL, NULL, &ndisBuf, &ndisPacketLen);
  611. LOG("NdisToFirPacket, number of bytes: %d", ndisPacketLen);
  612. DEBUGFIR(DBG_OUT, ("NSC: NdisToFirPacket, number of bytes: %d\n", ndisPacketLen));
  613. /*
  614. * Make sure that the packet is big enough to be legal.
  615. * It consists of an A, C, and variable-length I field.
  616. */
  617. if (ndisPacketLen < IR_ADDR_SIZE + IR_CONTROL_SIZE){
  618. LOG("Error: packet too short in %d", ndisPacketLen);
  619. DEBUGFIR(DBG_ERR, ("NSC: packet too short in NdisToFirPacket (%d bytes)\n", ndisPacketLen));
  620. return FALSE;
  621. }
  622. /*
  623. * Make sure that we won't overwrite our contiguous buffer.
  624. */
  625. if (ndisPacketLen > TotalDmaBufferLength){
  626. /*
  627. * The packet is too large
  628. * Tell the caller to retry with a packet size large
  629. * enough to get past this stage next time.
  630. */
  631. LOG("Error: packet too large in %d ", ndisPacketLen);
  632. DEBUGFIR(DBG_ERR, ("NSC: Packet too large in NdisToIrPacket (%d=%xh bytes), MAX_IRDA_DATA_SIZE=%d, TotalDmaBufferLength=%d.\n",
  633. ndisPacketLen, ndisPacketLen, MAX_IRDA_DATA_SIZE, TotalDmaBufferLength));
  634. *ActualTransferLength = ndisPacketLen;
  635. return FALSE;
  636. }
  637. /*
  638. * Read the NDIS packet into a contiguous buffer.
  639. * We have to do this in two steps so that we can compute the
  640. * FCS BEFORE applying escape-byte transparency.
  641. */
  642. while (ndisBuf) {
  643. UCHAR *bufData;
  644. UINT bufLen;
  645. NdisQueryBufferSafe(ndisBuf, (PVOID *)&bufData, &bufLen,NormalPagePriority);
  646. if (bufData==NULL || (ndisPacketBytes + bufLen > ndisPacketLen)){
  647. /*
  648. * Packet was corrupt -- it misreported its size.
  649. */
  650. *ActualTransferLength = 0;
  651. ASSERT(0);
  652. return FALSE;
  653. }
  654. NdisMoveMemory((PVOID)(irPacketBuf+ndisPacketBytes),
  655. (PVOID)bufData, (ULONG)bufLen);
  656. ndisPacketBytes += bufLen;
  657. NdisGetNextBuffer(ndisBuf, &ndisBuf);
  658. }
  659. if (WPP_LEVEL_ENABLED(DBG_LOG_INFO)) {
  660. UCHAR CommandByte=*(irPacketBuf+1);
  661. UCHAR Nr=CommandByte >> 5;
  662. UCHAR Ns=(CommandByte >> 1) & 0x7;
  663. UCHAR Pf=(CommandByte >> 4) & 0x1;
  664. if ((CommandByte & 1) == 0) {
  665. LOG("Sending - I frame, Nr=%d, Ns=%d p/f=%d",Nr,Ns,Pf);
  666. } else {
  667. if ((CommandByte & 0x3) == 0x1) {
  668. LOG("Sending - S frame, Nr=%d, xx=%d, p/f=%d",Nr, (CommandByte > 2) & 0x3, Pf);
  669. } else {
  670. LOG("Sending - U frame, p/f=%d",Pf);
  671. }
  672. }
  673. }
  674. /*
  675. * Do a sanity check on the length of the packet.
  676. */
  677. if (ndisPacketBytes != ndisPacketLen){
  678. /*
  679. * Packet was corrupt -- it misreported its size.
  680. */
  681. LOG("Error: Packet corrupt in NdisToIrPacket "
  682. "(buffer lengths don't add up to packet length)");
  683. DEBUGFIR(DBG_ERR, ("NSC: Packet corrupt in NdisToIrPacket (buffer lengths don't add up to packet length).\n"));
  684. *ActualTransferLength = 0;
  685. return FALSE;
  686. }
  687. #ifdef DBG_ADD_PKT_ID
  688. if (addPktIdOn){
  689. static USHORT uniqueId = 0;
  690. DEBUGFIR(DBG_OUT, ("NSC: *** --> SEND PKT ID: %xh\n", (UINT)uniqueId));
  691. LOG("ID: Send (FIR) Pkt id: %x", uniqueId);
  692. *(USHORT *)(irPacketBuf+ndisPacketBytes) = uniqueId++;
  693. ndisPacketBytes += sizeof(USHORT);
  694. }
  695. #endif
  696. *ActualTransferLength = ndisPacketBytes;
  697. LOG("<== NdisToFirPacket");
  698. DEBUGFIR(DBG_OUT, ("NSC: <== NdisToFirPacket\n"));
  699. return TRUE;
  700. }