hnddma.c
上传用户:yuanda199
上传日期:2022-06-26
资源大小:412k
文件大小:19k
源码类别:

VxWorks

开发平台:

C/C++

  1. /*
  2.     Copyright 2001, Broadcom Corporation
  3.     All Rights Reserved.
  4.     
  5.     This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
  6.     the contents of this file may not be disclosed to third parties, copied or
  7.     duplicated in any form, in whole or in part, without the prior written
  8.     permission of Broadcom Corporation.
  9. */
  10. /*
  11.  * Generic Broadcom Home Networking Division (HND) DMA module.
  12.  * This supports the following chips: BCM42xx, 44xx, 47xx .
  13.  *
  14.  * Copyright(c) 2001, Broadcom Corp.
  15.  * $Id: hnddma.c,v 1.1 Broadcom SDK $
  16.  */
  17. #include <hnbutypedefs.h>
  18. #include <osl.h>
  19. #include <bcmendian.h>
  20. #include <bcmutils.h>
  21. struct dma_info; /* forward declaration */
  22. #define di_t struct dma_info
  23. #include <hnddma.h>
  24. /* debug/trace */
  25. #ifdef BCMDBG
  26. #define DMA_ERROR(args) if (!(*di->msg_level & 1)) ; else printf args
  27. #define DMA_TRACE(args) if (!(*di->msg_level & 2)) ; else printf args
  28. #else
  29. #define DMA_ERROR(args)
  30. #define DMA_TRACE(args)
  31. #endif
  32. /* default dma message level(if input msg_level pointer is null in dma_attach()) */
  33. static uint dma_msg_level = 0;
  34. #define MAXNAMEL 8
  35. #define MAXDD (DMAMAXRINGSZ / sizeof (dmadd_t))
  36. /* dma engine software state */
  37. typedef struct dma_info {
  38. hnddma_t hnddma; /* exported structure */
  39. uint *msg_level; /* message level pointer */
  40. char name[MAXNAMEL]; /* callers name for diag msgs */
  41. void *drv; /* driver handle */
  42. void *dev; /* device handle */
  43. dmaregs_t *regs; /* dma engine registers */
  44. dmadd_t *txd; /* pointer to chip-specific tx descriptor ring */
  45. uint txin; /* index of next descriptor to reclaim */
  46. uint txout; /* index of next descriptor to post */
  47. uint txavail; /* # free tx descriptors */
  48. void *txp[MAXDD]; /* parallel array of pointers to packets */
  49. void *txdpa; /* physical address of descriptor ring */
  50. uint txdalign; /* #bytes added to alloc'd mem to align txd */
  51. dmadd_t *rxd; /* pointer to chip-specific rx descriptor ring */
  52. uint rxin; /* index of next descriptor to reclaim */
  53. uint rxout; /* index of next descriptor to post */
  54. void *rxp[MAXDD]; /* parallel array of pointers to packets */
  55. void *rxdpa; /* physical address of descriptor ring */
  56. uint rxdalign; /* #bytes added to alloc'd mem to align rxd */
  57. /* tunables */
  58. uint ntxd; /* # tx descriptors */
  59. uint nrxd; /* # rx descriptors */
  60. uint rxbufsize; /* rx buffer size in bytes */
  61. uint nrxpost; /* # rx buffers to keep posted */
  62. uint rxoffset; /* rxcontrol offset */
  63. uint ddoffset; /* add to get dma address of descriptor ring */
  64. uint dataoffset; /* add to get dma address of data buffer */
  65. } dma_info_t;
  66. /* descriptor bumping macros */
  67. #define NEXTTXD(i) ((i + 1) & (di->ntxd - 1))
  68. #define PREVTXD(i) ((i - 1) & (di->ntxd - 1))
  69. #define NEXTRXD(i) ((i + 1) & (di->nrxd - 1))
  70. #define NTXDACTIVE(h, t) ((t - h) & (di->ntxd - 1))
  71. #define NRXDACTIVE(h, t) ((t - h) & (di->nrxd - 1))
  72. /* macros to convert between byte offsets and indexes */
  73. #define B2I(bytes) ((bytes) / sizeof (dmadd_t))
  74. #define I2B(index) ((index) * sizeof (dmadd_t))
  75. void*
  76. dma_attach(void *drv, void *dev, char *name, dmaregs_t *regs, uint ntxd, uint nrxd,
  77. uint rxbufsize, uint nrxpost, uint rxoffset, uint ddoffset, uint dataoffset, uint *msg_level)
  78. {
  79. dma_info_t *di;
  80. void *va;
  81. ASSERT(ntxd <= MAXDD);
  82. ASSERT(nrxd <= MAXDD);
  83. /* allocate private info structure */
  84. if ((di = MALLOC(sizeof (dma_info_t))) == NULL)
  85. return (NULL);
  86. bzero((char*)di, sizeof (dma_info_t));
  87. /* set message level */
  88. di->msg_level = msg_level ? msg_level : &dma_msg_level;
  89. DMA_TRACE(("%s: dma_attach: drv 0x%x dev 0x%x regs 0x%x ntxd %d nrxd %d rxbufsize %d nrxpost %d rxoffset %d ddoffset 0x%x dataoffset 0x%xn", name, (uint)drv, (uint)dev, (uint)regs, ntxd, nrxd, rxbufsize, nrxpost, rxoffset, ddoffset, dataoffset));
  90. /* make a private copy of our callers name */
  91. strncpy(di->name, name, MAXNAMEL);
  92. di->name[MAXNAMEL-1] = '';
  93. di->drv = drv;
  94. di->dev = dev;
  95. di->regs = regs;
  96. /* allocate transmit descriptor ring */
  97. if (ntxd) {
  98. if ((va = DMA_ALLOC_CONSISTENT(dev, (DMAMAXRINGSZ + DMARINGALIGN), &di->txdpa)) == NULL)
  99. goto fail;
  100. di->txd = (dmadd_t*) ROUNDUP(va, DMARINGALIGN);
  101. di->txdalign = ((uint)di->txd - (uint)va);
  102. di->txdpa = (void*) ((uint)di->txdpa + di->txdalign);
  103. ASSERT(ISALIGNED(di->txd, DMARINGALIGN));
  104. }
  105. /* allocate receive descriptor ring */
  106. if (nrxd) {
  107. if ((va = DMA_ALLOC_CONSISTENT(dev, (DMAMAXRINGSZ + DMARINGALIGN), &di->rxdpa)) == NULL)
  108. goto fail;
  109. di->rxd = (dmadd_t*) ROUNDUP(va, DMARINGALIGN);
  110. di->rxdalign = ((uint)di->rxd - (uint)va);
  111. di->rxdpa = (void*) ((uint)di->rxdpa + di->rxdalign);
  112. ASSERT(ISALIGNED(di->rxd, DMARINGALIGN));
  113. }
  114. /* save tunables */
  115. di->ntxd = ntxd;
  116. di->nrxd = nrxd;
  117. di->rxbufsize = rxbufsize;
  118. di->nrxpost = nrxpost;
  119. di->rxoffset = rxoffset;
  120. di->ddoffset = ddoffset;
  121. di->dataoffset = dataoffset;
  122. return ((void*)di);
  123. fail:
  124. dma_detach((void*)di);
  125. return (NULL);
  126. }
  127. void
  128. dma_detach(dma_info_t *di)
  129. {
  130. if (di == NULL)
  131. return;
  132. DMA_TRACE(("%s: dma_detachn", di->name));
  133. /* shouldn't be here if descriptors are unreclaimed */
  134. ASSERT(di->txin == di->txout);
  135. ASSERT(di->rxin == di->rxout);
  136. /* free dma descriptor rings */
  137. if (di->txd)
  138. DMA_FREE_CONSISTENT(di->dev, (void *)(di->txd - di->txdalign), (DMAMAXRINGSZ + DMARINGALIGN), di->txdpa);
  139. if (di->rxd)
  140. DMA_FREE_CONSISTENT(di->dev, (void *)(di->rxd - di->rxdalign), (DMAMAXRINGSZ + DMARINGALIGN), di->rxdpa);
  141. /* free our private info structure */
  142. MFREE((void*)di, sizeof (dma_info_t));
  143. }
  144. /* 
  145.  * PR2414 WAR: When the DMA channel is in the FetchDescriptor state,
  146.  * it does not notice that the enable bit has been turned off. If the
  147.  * enable bit is turned back on before the descriptor fetch completes,
  148.  * at least some of the DMA channel does not get reset. In particular,
  149.  * it will fetch a descriptor from the address it was trying to fetch
  150.  * from when it was disabled. 
  151.  *
  152.  * For all cores other than USB, the workaround is simply to clear the
  153.  * enable bit, and then read back status until the state shows up as
  154.  * Disabled before re-enabling the channel.
  155.  */
  156. void
  157. dma_txreset(dma_info_t *di)
  158. {
  159. uint32 status;
  160. DMA_TRACE(("%s: dma_txresetn", di->name));
  161. /* address PR8249/PR7577 issue */
  162. /* suspend tx DMA first */
  163. W_REG(&di->regs->xmtcontrol, XC_SE);
  164. SPINWAIT((status = (R_REG(&di->regs->xmtstatus) & XS_XS_MASK)) != XS_XS_DISABLED &&
  165.  status != XS_XS_IDLE &&
  166.  status != XS_XS_STOPPED,
  167.  10000);
  168. /* PR2414 WAR: DMA engines are not disabled until transfer finishes */
  169. W_REG(&di->regs->xmtcontrol, 0);
  170. SPINWAIT((status = (R_REG(&di->regs->xmtstatus) & XS_XS_MASK)) != XS_XS_DISABLED,
  171.  10000);
  172. if (status != XS_XS_DISABLED) {
  173. DMA_ERROR(("%s: dma_txreset: dma cannot be stoppedn", di->name));
  174. }
  175. /* wait for the last transaction to complete */
  176. OSL_DELAY(300);
  177. }
  178. void
  179. dma_rxreset(dma_info_t *di)
  180. {
  181. uint32 status;
  182. DMA_TRACE(("%s: dma_rxresetn", di->name));
  183. /* PR2414 WAR: DMA engines are not disabled until transfer finishes */
  184. W_REG(&di->regs->rcvcontrol, 0);
  185. SPINWAIT((status = (R_REG(&di->regs->rcvstatus) & RS_RS_MASK)) != RS_RS_DISABLED,
  186.  10000);
  187. if (status != RS_RS_DISABLED) {
  188. DMA_ERROR(("%s: dma_rxreset: dma cannot be stoppedn", di->name));
  189. }
  190. }
  191. void
  192. dma_txinit(dma_info_t *di)
  193. {
  194. DMA_TRACE(("%s: dma_txinitn", di->name));
  195. di->txin = di->txout = 0;
  196. di->txavail = di->ntxd - 1;
  197. /* clear tx descriptor ring */
  198. BZERO_SM((void*)di->txd, (di->ntxd * sizeof (dmadd_t)));
  199. W_REG(&di->regs->xmtcontrol, XC_XE);
  200. W_REG(&di->regs->xmtaddr, ((uint32)di->txdpa + di->ddoffset));
  201. }
  202. bool
  203. dma_txenabled(dma_info_t *di)
  204. {
  205. uint32 xc;
  206. /* If the chip is dead, it is not enabled :-) */
  207. xc = R_REG(&di->regs->xmtcontrol);
  208. return ((xc != 0xffffffff) && (xc & XC_XE));
  209. }
  210. void
  211. dma_txsuspend(dma_info_t *di)
  212. {
  213. DMA_TRACE(("%s: dma_txsuspendn", di->name));
  214. OR_REG(&di->regs->xmtcontrol, XC_SE);
  215. }
  216. void
  217. dma_txresume(dma_info_t *di)
  218. {
  219. DMA_TRACE(("%s: dma_txresumen", di->name));
  220. AND_REG(&di->regs->xmtcontrol, ~XC_SE);
  221. }
  222. bool
  223. dma_txsuspended(dma_info_t *di)
  224. {
  225. uint32 xc;
  226. uint32 xs;
  227. xc = R_REG(&di->regs->xmtcontrol);
  228. if (xc & XC_SE) {
  229. xs = R_REG(&di->regs->xmtstatus);
  230. return ((xs & XS_XS_MASK) == XS_XS_IDLE);
  231. }
  232. return 0;
  233. }
  234. bool
  235. dma_txstopped(dma_info_t *di)
  236. {
  237. return ((R_REG(&di->regs->xmtstatus) & XS_XS_MASK) == XS_XS_STOPPED);
  238. }
  239. bool
  240. dma_rxstopped(dma_info_t *di)
  241. {
  242. return ((R_REG(&di->regs->rcvstatus) & RS_RS_MASK) == RS_RS_STOPPED);
  243. }
  244. void
  245. dma_fifoloopbackenable(dma_info_t *di)
  246. {
  247. DMA_TRACE(("%s: dma_fifoloopbackenablen", di->name));
  248. OR_REG(&di->regs->xmtcontrol, XC_LE);
  249. }
  250. void
  251. dma_rxinit(dma_info_t *di)
  252. {
  253. DMA_TRACE(("%s: dma_rxinitn", di->name));
  254. di->rxin = di->rxout = 0;
  255. /* clear rx descriptor ring */
  256. BZERO_SM((void*)di->rxd, (di->nrxd * sizeof (dmadd_t)));
  257. dma_rxenable(di);
  258. W_REG(&di->regs->rcvaddr, ((uint32)di->rxdpa + di->ddoffset));
  259. }
  260. void
  261. dma_rxenable(dma_info_t *di)
  262. {
  263. DMA_TRACE(("%s: dma_rxenablen", di->name));
  264. W_REG(&di->regs->rcvcontrol, ((di->rxoffset << RC_RO_SHIFT) | RC_RE));
  265. }
  266. bool
  267. dma_rxenabled(dma_info_t *di)
  268. {
  269. uint32 rc;
  270. rc = R_REG(&di->regs->rcvcontrol);
  271. return ((rc != 0xffffffff) && (rc & RC_RE));
  272. }
  273. /*
  274.  * The BCM47XX family supports full 32bit dma engine buffer addressing so
  275.  * dma buffers can cross 4 Kbyte page boundaries.
  276.  */
  277. int
  278. dma_txfast(dma_info_t *di, void *p0, uint32 coreflags)
  279. {
  280. void *p, *next;
  281. uchar *data;
  282. uint len;
  283. uint txout;
  284. uint32 ctrl;
  285. uint32 pa;
  286. DMA_TRACE(("%s: dma_txfastn", di->name));
  287. txout = di->txout;
  288. ctrl = 0;
  289. /*
  290.  * Walk the chain of packet buffers
  291.  * allocating and initializing transmit descriptor entries.
  292.  */
  293. for (p = p0; p; p = next) {
  294. data = PKTDATA(di->drv, p);
  295. len = PKTLEN(di->drv, p);
  296. next = PKTNEXT(di->drv, p);
  297. /* return nonzero if out of tx descriptors */
  298. if (NEXTTXD(txout) == di->txin)
  299. goto outoftxd;
  300. /* PR988 - skip zero length buffers */
  301. if (len == 0)
  302. continue;
  303. /* get physical address of buffer start */
  304. pa = (uint32) DMA_MAP(di->dev, data, len, DMA_TX, p);
  305. /* build the descriptor control value */
  306. ctrl = len & CTRL_BC_MASK;
  307. /* PR3697: Descriptor flags are not ignored for descriptors where SOF is clear */
  308. ctrl |= coreflags;
  309. if (p == p0)
  310. ctrl |= CTRL_SOF;
  311. if (next == NULL)
  312. ctrl |= (CTRL_IOC | CTRL_EOF);
  313. if (txout == (di->ntxd - 1))
  314. ctrl |= CTRL_EOT;
  315. /* init the tx descriptor */
  316. W_SM(&di->txd[txout].ctrl, BUS_SWAP32(ctrl));
  317. W_SM(&di->txd[txout].addr, BUS_SWAP32(pa + di->dataoffset));
  318. ASSERT(di->txp[txout] == NULL);
  319. txout = NEXTTXD(txout);
  320. }
  321. /* if last txd eof not set, fix it */
  322. if (!(ctrl & CTRL_EOF))
  323. W_SM(&di->txd[PREVTXD(txout)].ctrl, BUS_SWAP32(ctrl | CTRL_IOC | CTRL_EOF));
  324. /* save the packet */
  325. di->txp[di->txout] = p0;
  326. /* bump the tx descriptor index */
  327. di->txout = txout;
  328. /* kick the chip */
  329. W_REG(&di->regs->xmtptr, I2B(txout));
  330. /* tx flow control */
  331. di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
  332. return (0);
  333. outoftxd:
  334. DMA_ERROR(("%s: dma_txfast: out of txdsn", di->name));
  335. PKTFREE(di->drv, p0, TRUE);
  336. di->txavail = 0;
  337. di->hnddma.txnobuf++;
  338. return (-1);
  339. }
  340. #define PAGESZ 4096
  341. #define PAGEBASE(x) ((uint)(x) & ~4095)
  342. /*
  343.  * Just like above except go through the extra effort of splitting
  344.  * buffers that cross 4Kbyte boundaries into multiple tx descriptors.
  345.  */
  346. int
  347. dma_tx(dma_info_t *di, void *p0, uint32 coreflags)
  348. {
  349. void *p, *next;
  350. uchar *data;
  351. uint plen, len;
  352. uchar *page, *start, *end;
  353. uint txout;
  354. uint32 ctrl;
  355. uint32 pa;
  356. DMA_TRACE(("%s: dma_txn", di->name));
  357. txout = di->txout;
  358. ctrl = 0;
  359. /*
  360.  * Walk the chain of packet buffers
  361.  * splitting those that cross 4 Kbyte boundaries
  362.  * allocating and initializing transmit descriptor entries.
  363.  */
  364. for (p = p0; p; p = next) {
  365. data = PKTDATA(di->drv, p);
  366. plen = PKTLEN(di->drv, p);
  367. next = PKTNEXT(di->drv, p);
  368. /* PR988 - skip zero length buffers */
  369. if (plen == 0)
  370. continue;
  371. for (page = (uchar*)PAGEBASE(data);
  372. page <= (uchar*)PAGEBASE(data + plen - 1);
  373. page += PAGESZ) {
  374. /* return nonzero if out of tx descriptors */
  375. if (NEXTTXD(txout) == di->txin)
  376. goto outoftxd;
  377. start = (page == (uchar*)PAGEBASE(data))?  data: page;
  378. end = (page == (uchar*)PAGEBASE(data + plen))?
  379. (data + plen): (page + PAGESZ);
  380. len = end - start;
  381. /* build the descriptor control value */
  382. ctrl = len & CTRL_BC_MASK;
  383. /* PR3697: Descriptor flags are not ignored for descriptors where SOF is clear */
  384. ctrl |= coreflags;
  385. if ((p == p0) && (start == data))
  386. ctrl |= CTRL_SOF;
  387. if ((next == NULL) && (end == (data + plen)))
  388. ctrl |= (CTRL_IOC | CTRL_EOF);
  389. if (txout == (di->ntxd - 1))
  390. ctrl |= CTRL_EOT;
  391. /* get physical address of buffer start */
  392. pa = (uint32) DMA_MAP(di->dev, start, len, DMA_TX, p);
  393. /* init the tx descriptor */
  394. W_SM(&di->txd[txout].ctrl, BUS_SWAP32(ctrl));
  395. W_SM(&di->txd[txout].addr, BUS_SWAP32(pa + di->dataoffset));
  396. ASSERT(di->txp[txout] == NULL);
  397. txout = NEXTTXD(txout);
  398. }
  399. }
  400. /* if last txd eof not set, fix it */
  401. if (!(ctrl & CTRL_EOF))
  402. W_SM(&di->txd[PREVTXD(txout)].ctrl, BUS_SWAP32(ctrl | CTRL_IOC | CTRL_EOF));
  403. /* save the packet */
  404. di->txp[di->txout] = p0;
  405. /* bump the tx descriptor index */
  406. di->txout = txout;
  407. /* kick the chip */
  408. W_REG(&di->regs->xmtptr, I2B(txout));
  409. /* tx flow control */
  410. di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
  411. return (0);
  412. outoftxd:
  413. DMA_ERROR(("%s: dma_tx: out of txdsn", di->name));
  414. PKTFREE(di->drv, p0, TRUE);
  415. di->txavail = 0;
  416. di->hnddma.txnobuf++;
  417. return (-1);
  418. }
  419. /* returns a pointer to the next frame received, or NULL if there are no more */
  420. void*
  421. dma_rx(dma_info_t *di)
  422. {
  423. void *p;
  424. uint len;
  425. int skiplen = 0;
  426. while ((p = dma_getnextrxp(di, FALSE))) {
  427. /* skip giant packets which span multiple rx descriptors */
  428. if (skiplen > 0) {
  429. skiplen -= di->rxbufsize;
  430. if (skiplen < 0)
  431. skiplen = 0;
  432. PKTFREE(di->drv, p, FALSE);
  433. continue;
  434. }
  435. len = ltoh16(*(uint16*)(PKTDATA(di->drv, p)));
  436. DMA_TRACE(("%s: dma_rx len %dn", di->name, len));
  437. /* bad frame length check */
  438. if (len > (di->rxbufsize - di->rxoffset)) {
  439. DMA_ERROR(("%s: dma_rx: bad frame length (%d)n", di->name, len));
  440. if (len > 0)
  441. skiplen = len - (di->rxbufsize - di->rxoffset);
  442. PKTFREE(di->drv, p, FALSE);
  443. di->hnddma.rxgiants++;
  444. continue;
  445. }
  446. /* set actual length */
  447. PKTSETLEN(di->drv, p, (di->rxoffset + len));
  448. break;
  449. }
  450. return (p);
  451. }
  452. /* post receive buffers */
  453. void
  454. dma_rxfill(dma_info_t *di)
  455. {
  456. void *p;
  457. uint rxin, rxout;
  458. uint ctrl;
  459. uint n;
  460. uint i;
  461. uint32 pa;
  462. uint rxbufsize;
  463. /*
  464.  * Determine how many receive buffers we're lacking
  465.  * from the full complement, allocate, initialize,
  466.  * and post them, then update the chip rx lastdscr.
  467.  */
  468. rxin = di->rxin;
  469. rxout = di->rxout;
  470. rxbufsize = di->rxbufsize;
  471. n = di->nrxpost - NRXDACTIVE(rxin, rxout);
  472. DMA_TRACE(("%s: dma_rxfill: post %dn", di->name, n));
  473. for (i = 0; i < n; i++) {
  474. if ((p = PKTGET(di->drv, rxbufsize, FALSE)) == NULL) {
  475. DMA_ERROR(("%s: dma_rxfill: out of rxbufsn", di->name));
  476. di->hnddma.rxnobuf++;
  477. break;
  478. }
  479. /* PR3263 & PR3387 & PR4642 war: rxh.len=0 means dma writes not complete */
  480. *(uint32*)(OSL_UNCACHED(PKTDATA(di->drv, p))) = 0;
  481. pa = (uint32) DMA_MAP(di->dev, PKTDATA(di->drv, p), rxbufsize, DMA_RX, p);
  482. ASSERT(ISALIGNED(pa, 4));
  483. /* save the free packet pointer */
  484. #if 0
  485. ASSERT(di->rxp[rxout] == NULL);
  486. #endif
  487. di->rxp[rxout] = p;
  488. /* paranoia */
  489. ASSERT(R_SM(&di->rxd[rxout].addr) == 0);
  490. /* prep the descriptor control value */
  491. ctrl = rxbufsize;
  492. if (rxout == (di->nrxd - 1))
  493. ctrl |= CTRL_EOT;
  494. /* init the rx descriptor */
  495. W_SM(&di->rxd[rxout].ctrl, BUS_SWAP32(ctrl));
  496. W_SM(&di->rxd[rxout].addr, BUS_SWAP32(pa + di->dataoffset));
  497. rxout = NEXTRXD(rxout);
  498. }
  499. di->rxout = rxout;
  500. /* update the chip lastdscr pointer */
  501. W_REG(&di->regs->rcvptr, I2B(rxout));
  502. }
  503. void
  504. dma_txreclaim(dma_info_t *di, bool forceall)
  505. {
  506. void *p;
  507. DMA_TRACE(("%s: dma_txreclaim %sn", di->name, forceall ? "all" : ""));
  508. while ((p = dma_getnexttxp(di, forceall)))
  509. PKTFREE(di->drv, p, TRUE);
  510. }
  511. /*
  512.  * Reclaim next completed txd (txds if using chained buffers) and
  513.  * return associated packet.
  514.  * If 'force' is true, reclaim txd(s) and return associated packet
  515.  * regardless of the value of the hardware "curr" pointer.
  516.  */
  517. void*
  518. dma_getnexttxp(dma_info_t *di, bool forceall)
  519. {
  520. uint start, end, i;
  521. void *txp;
  522. DMA_TRACE(("%s: dma_getnexttxp %sn", di->name, forceall ? "all" : ""));
  523. txp = NULL;
  524. /* if forcing, dma engine must be disabled */
  525. ASSERT(!forceall || !dma_txenabled(di));
  526. start = di->txin;
  527. if (forceall)
  528. end = di->txout;
  529. else
  530. end = B2I(R_REG(&di->regs->xmtstatus) & XS_CD_MASK);
  531. /* PR4738 - xmt disable/re-enable does not clear CURR */
  532. if ((start == 0) && (end > di->txout))
  533. goto bogus;
  534. for (i = start; i != end && !txp; i = NEXTTXD(i)) {
  535. DMA_UNMAP(di->dev, (BUS_SWAP32(R_SM(&di->txd[i].addr)) - di->dataoffset),
  536.   (BUS_SWAP32(R_SM(&di->txd[i].ctrl)) & CTRL_BC_MASK), DMA_TX, di->txp[i]);
  537. W_SM(&di->txd[i].addr, 0);
  538. txp = di->txp[i];
  539. di->txp[i] = NULL;
  540. }
  541. di->txin = i;
  542. /* tx flow control */
  543. di->txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
  544. return (txp);
  545. bogus:
  546. /*
  547. DMA_ERROR(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %dn",
  548. start, end, di->txout, forceall));
  549. */
  550. return (NULL);
  551. }
  552. void
  553. dma_rxreclaim(dma_info_t *di)
  554. {
  555. void *p;
  556. DMA_TRACE(("%s: dma_rxreclaimn", di->name));
  557. while ((p = dma_getnextrxp(di, TRUE)))
  558. PKTFREE(di->drv, p, FALSE);
  559. }
  560. void *
  561. dma_getnextrxp(dma_info_t *di, bool forceall)
  562. {
  563. uint i;
  564. void *rxp;
  565. /* if forcing, dma engine must be disabled */
  566. ASSERT(!forceall || !dma_rxenabled(di));
  567. i = di->rxin;
  568. /* return if no packets posted */
  569. if (i == di->rxout)
  570. return (NULL);
  571. /* ignore curr if forceall */
  572. if (!forceall && (i == B2I(R_REG(&di->regs->rcvstatus) & RS_CD_MASK)))
  573. return (NULL);
  574. /* get the packet pointer that corresponds to the rx descriptor */
  575. rxp = di->rxp[i];
  576. ASSERT(rxp);
  577. di->rxp[i] = NULL;
  578. /* clear this packet from the descriptor ring */
  579. DMA_UNMAP(di->dev, (BUS_SWAP32(R_SM(&di->rxd[i].addr)) - di->dataoffset),
  580.   di->rxbufsize, DMA_RX, rxp);
  581. W_SM(&di->rxd[i].addr, 0);
  582. di->rxin = NEXTRXD(i);
  583. return (rxp);
  584. }
  585. char*
  586. dma_dump(dma_info_t *di, char *buf)
  587. {
  588. buf += sprintf(buf, "txd 0x%lx txdpa 0x%lx txp 0x%lx txin %d txout %dn",
  589. (ulong)di->txd, (ulong)di->txdpa, (ulong)di->txp, di->txin, di->txout);
  590. buf += sprintf(buf, "rxd 0x%lx rxdpa 0x%lx rxp 0x%lx rxin %d rxout %dn",
  591. (ulong)di->rxd, (ulong)di->rxdpa, (ulong)di->rxp, di->rxin, di->rxout);
  592. buf += sprintf(buf, "xmtcontrol 0x%x xmtaddr 0x%x xmtptr 0x%x xmtstatus 0x%xn",
  593. R_REG(&di->regs->xmtcontrol),
  594. R_REG(&di->regs->xmtaddr),
  595. R_REG(&di->regs->xmtptr),
  596. R_REG(&di->regs->xmtstatus));
  597. buf += sprintf(buf, "rcvcontrol 0x%x rcvaddr 0x%x rcvptr 0x%x rcvstatus 0x%xn",
  598. R_REG(&di->regs->rcvcontrol),
  599. R_REG(&di->regs->rcvaddr),
  600. R_REG(&di->regs->rcvptr),
  601. R_REG(&di->regs->rcvstatus));
  602. return (buf);
  603. }
  604. uint
  605. dma_getvar(dma_info_t *di, char *name)
  606. {
  607. if (!strcmp(name, "&txavail"))
  608. return ((uint) &di->txavail);
  609. else {
  610. ASSERT(0);
  611. }
  612. return (0);
  613. }