dma1.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. /************************************************************
  2. *
  3. * copyright @ Motorola, 1999
  4. *
  5. * App. API
  6. *
  7. * App. API are the APIs Kernel provides for the application
  8. * level program
  9. *
  10. ************************************************************/
  11. #include "dma_export.h"
  12. #include "dma.h"
  13. /* Define a macro to use an optional application-layer print function, if
  14. * one was passed to the library during initialization. If there was no
  15. * function pointer passed, this protects against referencing a NULL pointer.
  16. * Also define The global variable that holds the passed pointer.
  17. */
  18. #define PRINT if ( app_print ) app_print
  19. static int (*app_print)(char *,...);
  20. /* Set by call to get_eumbbar during DMA_Initialize.
  21. * This could be globally available to the library, but there is
  22. * an advantage to passing it as a parameter: it is already in a register
  23. * and doesn't have to be loaded from memory. Also, that is the way the
  24. * library was already implemented and I don't want to change it without
  25. * a more detailed analysis.
  26. * It is being set as a global variable during initialization to hide it from
  27. * the DINK application layer, because it is Kahlua-specific. I think that
  28. * get_eumbbar, load_runtime_reg, and store_runtime_reg should be defined in
  29. * a Kahlua-specific library dealing with the embedded utilities memory block.
  30. * Right now, get_eumbbar is defined in dink32/kahlua.s. The other two are
  31. * defined in dink32/drivers/i2c/i2c2.s, drivers/dma/dma2.s, etc.
  32. */
  33. static unsigned int Global_eumbbar = 0;
  34. extern unsigned int get_eumbbar();
  35. extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg );
  36. #pragma Alias( load_runtime_reg, "load_runtime_reg" );
  37. extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val );
  38. #pragma Alias( store_runtime_reg, "store_runtime_reg" );
  39. unsigned int dma_reg_tb[][14] = {
  40. /* local DMA registers */
  41. {
  42. /* DMA_0_MR */ 0x00001100,
  43. /* DMA_0_SR */ 0x00001104,
  44. /* DMA_0_CDAR */ 0x00001108,
  45. /* DMA_0_SAR */ 0x00001110,
  46. /* DMA_0_DAR */ 0x00001118,
  47. /* DMA_0_BCR */ 0x00001120,
  48. /* DMA_0_NDAR */ 0x00001124,
  49. /* DMA_1_MR */ 0x00001200,
  50. /* DMA_1_SR */ 0x00001204,
  51. /* DMA_1_CDAR */ 0x00001208,
  52. /* DMA_1_SAR */ 0x00001210,
  53. /* DMA_1_DAR */ 0x00001218,
  54. /* DMA_1_BCR */ 0x00001220,
  55. /* DMA_1_NDAR */ 0x00001224,
  56. },
  57. /* remote DMA registers */
  58. {
  59. /* DMA_0_MR */ 0x00000100,
  60. /* DMA_0_SR */ 0x00000104,
  61. /* DMA_0_CDAR */ 0x00000108,
  62. /* DMA_0_SAR */ 0x00000110,
  63. /* DMA_0_DAR */ 0x00000118,
  64. /* DMA_0_BCR */ 0x00000120,
  65. /* DMA_0_NDAR */ 0x00000124,
  66. /* DMA_1_MR */ 0x00000200,
  67. /* DMA_1_SR */ 0x00000204,
  68. /* DMA_1_CDAR */ 0x00000208,
  69. /* DMA_1_SAR */ 0x00000210,
  70. /* DMA_1_DAR */ 0x00000218,
  71. /* DMA_1_BCR */ 0x00000220,
  72. /* DMA_1_NDAR */ 0x00000224,
  73. },
  74. };
  75. /* API functions */
  76. /* Initialize DMA unit with the following:
  77. * optional pointer to application layer print function
  78. *
  79. * These parameters may be added:
  80. * ???
  81. * Interrupt enables, modes, etc. are set for each transfer.
  82. *
  83. * This function must be called before DMA unit can be used.
  84. */
  85. extern
  86. DMA_Status DMA_Initialize( int (*p)(char *,...))
  87. {
  88. DMAStatus status;
  89. /* establish the pointer, if there is one, to the application's "printf" */
  90. app_print = p;
  91. /* If this is the first call, get the embedded utilities memory block
  92. * base address. I'm not sure what to do about error handling here:
  93. * if a non-zero value is returned, accept it.
  94. */
  95. if ( Global_eumbbar == 0)
  96. Global_eumbbar = get_eumbbar();
  97. if ( Global_eumbbar == 0)
  98. {
  99. PRINT( "DMA_Initialize: can't find EUMBBAR\n" );
  100. return DMA_ERROR;
  101. }
  102. return DMA_SUCCESS;
  103. }
  104. /* Perform the DMA transfer, only direct mode is currently implemented.
  105. * At this point, I think it would be better to define a different
  106. * function for chaining mode.
  107. * Also, I'm not sure if it is appropriate to have the "generic" API
  108. * accept snoop and int_steer parameters. The DINK user interface allows
  109. * them, so for now I'll leave them.
  110. *
  111. * int_steer controls DMA interrupt steering to PCI or local processor
  112. * type is the type of transfer: M2M, M2P, P2M, P2P
  113. * source is the source address of the data
  114. * dest is the destination address of the data
  115. * len is the length of data to transfer
  116. * channel is the DMA channel to use for the transfer
  117. * snoop is the snoop enable control
  118. */
  119. extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer,
  120. DMA_TRANSFER_TYPE type,
  121. unsigned int source,
  122. unsigned int dest,
  123. unsigned int len,
  124. DMA_CHANNEL channel,
  125. DMA_SNOOP_MODE snoop)
  126. {
  127. DMA_MR md;
  128. DMA_CDAR cdar;
  129. /* it's inappropriate for curr to be a struct, but I'll leave it */
  130. DMA_CURR curr;
  131. DMAStatus stat;
  132. /* The rest of this code was moved from device.c test_dma to here.
  133. * It needs to be cleaned up and validated, but at least it is removed
  134. * from the application and API. Most of the mode is left hard coded.
  135. * This should be changed after the final API is defined and the user
  136. * application has a way to control the transfer.
  137. *
  138. */
  139. if ( DMA_Get_Mode( LOCAL, Global_eumbbar, channel, &md ) != DMASUCCESS )
  140. {
  141. return DMA_ERROR;
  142. }
  143. md.irqs = int_steer;
  144. md.pde = 0;
  145. md.dahts = 3; /* 8 - byte */
  146. md.sahts = 3; /* 8 - byte */
  147. md.dahe = 0;
  148. md.sahe = 0;
  149. md.prc = 0;
  150. /* if steering interrupts to local processor, use polling mode */
  151. if ( int_steer == DMA_INT_STEER_PCI )
  152. {
  153. md.eie = 1;
  154. md.eotie = 1;
  155. } else {
  156. md.eie = 0;
  157. md.eotie = 0;
  158. }
  159. md.dl = 0;
  160. md.ctm = 1; /* direct mode */
  161. md.cc = 0;
  162. /* validate the length range */
  163. if (len > 0x3ffffff )
  164. {
  165. PRINT( "dev DMA: length of transfer too large: %d\n", len );
  166. return DMA_ERROR;
  167. }
  168. /* inappropriate to use a struct, but leave as is for now */
  169. curr.src_addr = source;
  170. curr.dest_addr = dest;
  171. curr.byte_cnt = len;
  172. (void)DMA_Poke_Desp( LOCAL, Global_eumbbar, channel, &cdar );
  173. cdar.snen = snoop;
  174. cdar.ctt = type;
  175. if ( ( stat = DMA_Bld_Desp( LOCAL, Global_eumbbar, channel, cdar ))
  176. != DMASUCCESS ||
  177. ( stat = DMA_Bld_Curr( LOCAL, Global_eumbbar, channel, curr ))
  178. != DMASUCCESS ||
  179. ( stat = DMA_Set_Mode( LOCAL, Global_eumbbar, channel, md ))
  180. != DMASUCCESS ||
  181. ( stat = DMA_Start( LOCAL, Global_eumbbar, channel ))
  182. != DMASUCCESS )
  183. {
  184. if ( stat == DMACHNBUSY )
  185. {
  186. PRINT( "dev DMA: channel %d busy.\n", channel );
  187. }
  188. else
  189. {
  190. PRINT( "dev DMA: invalid channel request.\n", channel );
  191. }
  192. return DMA_ERROR;
  193. }
  194. /* Since we are interested at the DMA performace right now,
  195. we are going to do as less as possible to burden the
  196. 603e core.
  197. if you have epic enabled or don't care the return from
  198. DMA operation, you can just return SUCCESS.
  199. if you don't have epic enabled and care the DMA result,
  200. you can use the polling method below.
  201. Note: I'll attempt to activate the code for handling polling.
  202. */
  203. #if 0
  204. /* if steering interrupt to local processor, let it handle results */
  205. if ( int_steer == DMA_INT_STEER_LOCAL )
  206. {
  207. return DMA_SUCCESS;
  208. }
  209. /* polling since interrupt goes to PCI */
  210. do
  211. {
  212. stat = DMA_ISR( Global_eumbbar, channel, dma_error_func,
  213. dma_error_func, dma_error_func, dma_error_func );
  214. }
  215. while ( stat == DMANOEVENT );
  216. #endif
  217. return DMA_SUCCESS;
  218. }
  219. /* DMA library internal functions */
  220. /**
  221. * Note:
  222. *
  223. * In all following functions, the host (KAHLUA) processor has a
  224. * choice of accessing on board local DMA (LOCAL),
  225. * or DMA on a distributed KAHLUA (REMOTE). In either case,
  226. * the caller shall pass the configured embedded utility memory
  227. * block base address relative to the DMA. If LOCAL DMA is used,
  228. * this parameter shall be EUMBBAR, if REMOTE is used, the
  229. * parameter shall be the corresponding PCSRBAR.
  230. **/
  231. /**************************************************************
  232. * function: DMA_Get_Stat
  233. *
  234. * description: return the content of status register of
  235. * the given DMA channel
  236. *
  237. * if error, reserved0 field all 1s.
  238. **************************************************************/
  239. static
  240. DMAStatus DMA_Get_Stat( LOCATION host, unsigned int eumbbar, unsigned int channel, DMA_SR *stat )
  241. {
  242. unsigned int tmp;
  243. if ( channel != 0 && channel != 1 || stat == 0 )
  244. {
  245. return DMAINVALID;
  246. }
  247. tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG] );
  248. #ifdef DMADBG0
  249. PRINT( "%s(%d): %s DMA %d (0x%08x) stat = 0x%08x\n", __FILE__, __LINE__,
  250. ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG], tmp );
  251. #endif
  252. stat->reserved0 = ( tmp & 0xffffff00 ) >> 8;
  253. stat->lme = ( tmp & 0x00000080 ) >> 7;
  254. stat->reserved1 = ( tmp & 0x00000060 ) >> 5;
  255. stat->pe = ( tmp & 0x00000010 ) >> 4;
  256. stat->reserved2 = ( tmp & 0x00000008 ) >> 3;
  257. stat->cb = ( tmp & 0x00000004 ) >> 2;
  258. stat->eosi = ( tmp & 0x00000002 ) >> 1;
  259. stat->eocai = ( tmp & 0x00000001 );
  260. return DMASUCCESS;
  261. }
  262. /**************************************************************
  263. * function: DMA_Get_Mode
  264. *
  265. * description: return the content of mode register of the
  266. * given DMA channel
  267. *
  268. * if error, return DMAINVALID, otherwise return
  269. * DMASUCCESS
  270. **************************************************************/
  271. static
  272. DMAStatus DMA_Get_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR *mode )
  273. {
  274. unsigned int tmp;
  275. if ( channel != 0 && channel != 1 || mode == 0 )
  276. {
  277. return DMAINVALID;
  278. }
  279. tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG] );
  280. #ifdef DMADBG0
  281. PRINT( "%s(%d): %s DMA %d (0x%08x) mode = 0x%08x\n", __FILE__, __LINE__,
  282. ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG], tmp );
  283. #endif
  284. mode->reserved0 = (tmp & 0xfff00000) >> 20;
  285. mode->irqs = (tmp & 0x00080000) >> 19;
  286. mode->pde = (tmp & 0x00040000) >> 18;
  287. mode->dahts = (tmp & 0x00030000) >> 16;
  288. mode->sahts = (tmp & 0x0000c000) >> 14;
  289. mode->dahe = (tmp & 0x00002000) >> 13;
  290. mode->sahe = (tmp & 0x00001000) >> 12;
  291. mode->prc = (tmp & 0x00000c00) >> 10;
  292. mode->reserved1 = (tmp & 0x00000200) >> 9;
  293. mode->eie = (tmp & 0x00000100) >> 8;
  294. mode->eotie = (tmp & 0x00000080) >> 7;
  295. mode->reserved2 = (tmp & 0x00000070) >> 4;
  296. mode->dl = (tmp & 0x00000008) >> 3;
  297. mode->ctm = (tmp & 0x00000004) >> 2;
  298. mode->cc = (tmp & 0x00000002) >> 1;
  299. mode->cs = (tmp & 0x00000001);
  300. return DMASUCCESS;
  301. }
  302. /**************************************************************
  303. * function: DMA_Set_Mode
  304. *
  305. * description: Set a new mode to a given DMA channel
  306. *
  307. * note: It is not a good idea of changing the DMA mode during
  308. * the middle of a transaction.
  309. **************************************************************/
  310. static
  311. DMAStatus DMA_Set_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR mode )
  312. {
  313. unsigned int tmp;
  314. if ( channel != 0 && channel != 1 )
  315. {
  316. return DMAINVALID;
  317. }
  318. tmp = ( mode.reserved0 & 0xfff ) << 20;
  319. tmp |= ( ( mode.irqs & 0x1 ) << 19);
  320. tmp |= ( ( mode.pde & 0x1 ) << 18 );
  321. tmp |= ( ( mode.dahts & 0x3 ) << 16 );
  322. tmp |= ( ( mode.sahts & 0x3 ) << 14 );
  323. tmp |= ( ( mode.dahe & 0x1 ) << 13 );
  324. tmp |= ( ( mode.sahe & 0x1 ) << 12 );
  325. tmp |= ( ( mode.prc & 0x3 ) << 10 );
  326. tmp |= ( ( mode.reserved1 & 0x1 ) << 9 );
  327. tmp |= ( ( mode.eie & 0x1 ) << 8 );
  328. tmp |= ( ( mode.eotie & 0x1 ) << 7 );
  329. tmp |= ( ( mode.reserved2 & 0x7 ) << 4 );
  330. tmp |= ( ( mode.dl & 0x1 ) << 3 );
  331. tmp |= ( ( mode.ctm & 0x1 ) << 2 );
  332. tmp |= ( ( mode.cc & 0x1 ) << 1 ) ;
  333. tmp |= ( mode.cs & 0x1 );
  334. store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], tmp );
  335. return DMASUCCESS;
  336. }
  337. /************************************************************
  338. * function: DMA_Start
  339. *
  340. * description: start a given DMA channel transaction
  341. * return DMASUCCESS if success otherwise return
  342. * DMAStatus value
  343. *
  344. * note: this function will clear DMA_MR(CC) first, then
  345. * set DMA_MR(CC).
  346. ***********************************************************/
  347. static
  348. DMAStatus DMA_Start( LOCATION host, unsigned int eumbbar, unsigned int channel )
  349. {
  350. DMA_SR stat;
  351. unsigned int mode;
  352. if ( channel != 0 && channel != 1 )
  353. {
  354. return DMAINVALID;
  355. }
  356. if ( DMA_Get_Stat( host, eumbbar, channel, &stat ) != DMASUCCESS )
  357. {
  358. return DMAINVALID;
  359. }
  360. if ( stat.cb == 1 )
  361. {
  362. /* DMA is not free */
  363. return DMACHNBUSY;
  364. }
  365. mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG] );
  366. /* clear DMA_MR(CS) */
  367. mode &= 0xfffffffe;
  368. store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
  369. /* set DMA_MR(CS) */
  370. mode |= CS;
  371. store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
  372. return DMASUCCESS;
  373. }
  374. /***********************************************************
  375. * function: DMA_Halt
  376. *
  377. * description: halt the current dma transaction on the specified
  378. * channel.
  379. * return DMASUCCESS if success otherwise return DMAINVALID
  380. *
  381. * note: if the specified DMA channel is idle, nothing happens
  382. *************************************************************/
  383. static
  384. DMAStatus DMA_Halt( LOCATION host, unsigned int eumbbar, unsigned int channel )
  385. {
  386. unsigned int mode;
  387. if ( channel != 0 && channel != 1 )
  388. {
  389. return DMAINVALID;
  390. }
  391. mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG]);
  392. /* clear DMA_MR(CS) */
  393. mode &= 0xfffffffe;
  394. store_runtime_reg(eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
  395. return DMASUCCESS;
  396. }
  397. /*************************************************************
  398. * function: DMA_Chn_Cnt
  399. *
  400. * description: set the DMA_MR(CC) bit for a given channel
  401. * that is in chaining mode.
  402. * return DMASUCCESS if successfule, otherwise return
  403. * DMAINVALID.
  404. *
  405. * note: if the given channel is not in chaining mode, nothing
  406. * happen.
  407. *
  408. *************************************************************/
  409. static
  410. DMAStatus DMA_Chn_Cnt( LOCATION host, unsigned int eumbbar, unsigned int channel )
  411. {
  412. DMA_MR mode;
  413. if ( channel != 0 && channel != 1 )
  414. {
  415. return DMAINVALID;
  416. }
  417. if ( DMA_Get_Mode( host, eumbbar, channel, &mode ) != DMASUCCESS )
  418. {
  419. return DMAINVALID;
  420. }
  421. if ( mode.ctm == 0 )
  422. {
  423. /* either illegal mode or not chaining mode */
  424. return DMAINVALID;
  425. }
  426. mode.cc = 1;
  427. return DMA_Set_Mode( host, eumbbar, channel, mode );
  428. }
  429. /**************************************************************
  430. * function: DMA_Bld_Desp
  431. *
  432. * description: set current descriptor address register
  433. * according to the desp for a given channel
  434. *
  435. * if the given channel is busy return DMACHNBUSY
  436. * and no change made, otherwise return DMASUCCESS.
  437. *
  438. * note:
  439. **************************************************************/
  440. static
  441. DMAStatus DMA_Bld_Desp( LOCATION host,
  442. unsigned int eumbbar,
  443. unsigned int channel,
  444. DMA_CDAR desp )
  445. {
  446. DMA_SR status;
  447. unsigned int temp;
  448. if ( channel != 0 && channel != 1 )
  449. {
  450. /* channel number out of range */
  451. return DMAINVALID;
  452. }
  453. if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS )
  454. {
  455. return DMAINVALID;
  456. }
  457. if ( status.cb == 1 )
  458. {
  459. /* channel busy */
  460. return DMACHNBUSY;
  461. }
  462. temp = ( desp.cda & 0x7ffffff ) << 5;
  463. temp |= (( desp.snen & 0x1 ) << 4 );
  464. temp |= (( desp.eosie & 0x1 ) << 3 );
  465. temp |= (( desp.ctt & 0x3 ) << 1 );
  466. temp |= ( desp.eotd & 0x1 );
  467. store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp );
  468. #ifdef DMADBG0
  469. PRINT( "%s(%d): %s DMA %d (0x%08x) cdar := 0x%08x\n", __FILE__, __LINE__,
  470. ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp );
  471. #endif
  472. return DMASUCCESS;
  473. }
  474. /**************************************************************
  475. * function: DMA_Poke_Desp
  476. *
  477. * description: poke the current descriptor address register
  478. * for a given channel
  479. *
  480. * return DMASUCCESS if no error
  481. *
  482. * note: Due to the undeterministic parallellism of DMA operation,
  483. * the value returned by this function shall be taken as
  484. * the most recently used descriptor when the last time
  485. * DMA starts a chaining mode operation.
  486. **************************************************************/
  487. static
  488. DMAStatus DMA_Poke_Desp( LOCATION host,
  489. unsigned int eumbbar,
  490. unsigned int channel,
  491. DMA_CDAR *desp )
  492. {
  493. unsigned int cdar;
  494. if ( channel != 0 && channel != 1 || desp == 0 )
  495. {
  496. return DMAINVALID;
  497. }
  498. cdar = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG] );
  499. #ifdef DMADBG0
  500. PRINT( "%s(%d): %s DMA %d (0x%08x) cdar : 0x%08x\n", __FILE__, __LINE__,
  501. ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], cdar );
  502. #endif
  503. desp->cda = ( cdar & 0xffffffe0 ) >> 5;
  504. desp->snen = ( cdar & 0x00000010 ) >> 4;
  505. desp->eosie = ( cdar & 0x00000008 ) >> 3;
  506. desp->ctt = ( cdar & 0x00000006 ) >> 1;
  507. desp->eotd = ( cdar & 0x00000001 );
  508. return DMASUCCESS;
  509. }
  510. /**************************************************************
  511. * function: DMA_Bld_Curr
  512. *
  513. * description: set current src, dest, byte count registers
  514. * according to the desp for a given channel
  515. * return DMASUCCESS if no error.
  516. *
  517. * note:
  518. **************************************************************/
  519. static
  520. DMAStatus DMA_Bld_Curr( LOCATION host,
  521. unsigned int eumbbar,
  522. unsigned int channel,
  523. DMA_CURR desp )
  524. {
  525. DMA_SR status;
  526. if ( channel != 0 && channel != 1 )
  527. {
  528. /* channel number out of range */
  529. return DMAINVALID;
  530. }
  531. if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS )
  532. {
  533. return DMAINVALID;
  534. }
  535. if ( status.cb == 1 )
  536. {
  537. /* channel busy */
  538. return DMACHNBUSY;
  539. }
  540. desp.byte_cnt &= 0x03ffffff; /* upper 6-bits are 0s */
  541. store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG], desp.src_addr );
  542. #ifdef DMADBG0
  543. PRINT( "%s(%d): %s DMA %d (0x%08x) src := 0x%08x\n", __FILE__, __LINE__,
  544. ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.src_addr );
  545. #endif
  546. store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG], desp.dest_addr );
  547. #ifdef DMADBG0
  548. PRINT( "%s(%d): %s DMA %d (0x%08x) dest := 0x%08x\n", __FILE__, __LINE__,
  549. ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.dest_addr );
  550. #endif
  551. store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG], desp.byte_cnt );
  552. #ifdef DMADBG0
  553. PRINT( "%s(%d): %s DMA %d (0x%08x) count := 0x%08x\n", __FILE__, __LINE__,
  554. ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.byte_cnt );
  555. #endif
  556. return DMASUCCESS;
  557. }
  558. /**************************************************************
  559. * function: DMA_Poke_Curr
  560. *
  561. * description: poke the current src, dest, byte count registers
  562. * for a given channel.
  563. *
  564. * return DMASUCCESS if no error
  565. *
  566. * note: Due to the undeterministic parallelism, in chaining
  567. * mode, the value returned by this function shall
  568. * be taken as reference when the query is made rather
  569. * than the absolute snapshot when the value is returned.
  570. **************************************************************/
  571. static
  572. DMAStatus DMA_Poke_Curr( LOCATION host,
  573. unsigned int eumbbar,
  574. unsigned int channel,
  575. DMA_CURR* desp )
  576. {
  577. if ( channel != 0 && channel != 1 || desp == 0 )
  578. {
  579. return DMAINVALID;
  580. }
  581. desp->src_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG] );
  582. #ifdef DMADBG0
  583. PRINT( "%s(%d): %s DMA %d (0x%08x) src : 0x%08x\n", __FILE__, __LINE__,
  584. ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->src_addr );
  585. #endif
  586. desp->dest_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG] );
  587. #ifdef DMADBG0
  588. PRINT( "%s(%d): %s DMA %d (0x%08x) dest : 0x%08x\n", __FILE__, __LINE__,
  589. ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->dest_addr );
  590. #endif
  591. desp->byte_cnt = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG] );
  592. #ifdef DMADBG0
  593. PRINT( "%s(%d): %s DMA %d (0x%08x) count : 0x%08x\n", __FILE__, __LINE__,
  594. ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->byte_cnt );
  595. #endif
  596. return DMASUCCESS;
  597. }
  598. /*****************************************************************
  599. * function: dma_error_func
  600. *
  601. * description: display the error information
  602. *
  603. * note: This seems like a highly convoluted way to handle messages,
  604. * but I'll leave it as it was in device.c when I moved it into the
  605. * DMA library source.
  606. ****************************************************************/
  607. static
  608. DMAStatus dma_error_func( unsigned int eumbbar, unsigned int chn, DMAStatus err)
  609. {
  610. unsigned char *msg[] =
  611. {
  612. "Local Memory Error",
  613. "PCI Error",
  614. "Channel Busy",
  615. "End-of-Segment Interrupt",
  616. "End-of-Chain/Direct Interrupt",
  617. };
  618. if ( err >= DMALMERROR && err <= DMAEOCAINT )
  619. {
  620. PRINT( "DMA Status: channel %d %s\n", chn, msg[err-DMASUCCESS-1] );
  621. }
  622. return err;
  623. }
  624. /*************************************************************
  625. * function: DMA_ISR
  626. *
  627. * description: DMA interrupt service routine
  628. * return DMAStatus value based on
  629. * the status
  630. *
  631. *************************************************************/
  632. static
  633. DMAStatus DMA_ISR( unsigned int eumbbar,
  634. unsigned int channel,
  635. DMAStatus (*lme_func)( unsigned int, unsigned int, DMAStatus ),
  636. DMAStatus (*pe_func) ( unsigned int, unsigned int, DMAStatus ),
  637. DMAStatus (*eosi_func)( unsigned int, unsigned int, DMAStatus ),
  638. DMAStatus (*eocai_func)(unsigned int, unsigned int, DMAStatus ))
  639. {
  640. DMA_SR stat;
  641. DMAStatus rval = DMANOEVENT;
  642. unsigned int temp;
  643. if ( channel != 0 && channel != 1 )
  644. {
  645. return DMAINVALID;
  646. }
  647. if ( DMA_Get_Stat( LOCAL, eumbbar, channel, &stat ) != DMASUCCESS )
  648. {
  649. return DMAINVALID;
  650. }
  651. if ( stat.lme == 1 )
  652. {
  653. /* local memory error */
  654. rval = DMALMERROR;
  655. if ( lme_func != 0 )
  656. {
  657. rval = (*lme_func)(eumbbar, channel, DMALMERROR );
  658. }
  659. }
  660. else if ( stat.pe == 1 )
  661. {
  662. /* PCI error */
  663. rval = DMAPERROR;
  664. if ( pe_func != 0 )
  665. {
  666. rval = (*pe_func)(eumbbar, channel, DMAPERROR );
  667. }
  668. }
  669. else if ( stat.eosi == 1 )
  670. {
  671. /* end-of-segment interrupt */
  672. rval = DMAEOSINT;
  673. if ( eosi_func != 0 )
  674. {
  675. rval = (*eosi_func)(eumbbar, channel, DMAEOSINT );
  676. }
  677. }
  678. else
  679. {
  680. /* End-of-chain/direct interrupt */
  681. rval = DMAEOCAINT;
  682. if ( eocai_func != 0 )
  683. {
  684. rval = (*eocai_func)(eumbbar, channel, DMAEOCAINT );
  685. }
  686. }
  687. temp = ( stat.reserved0 & 0xffffff ) << 8;
  688. temp |= ( ( stat.lme & 0x1 ) << 7 ); /* write one to clear */
  689. temp |= ( ( stat.reserved1 & 0x3 ) << 5 );
  690. temp |= ( ( stat.pe & 0x1 ) << 4 ); /* write one to clear */
  691. temp |= ( ( stat.reserved2 & 0x1 ) << 3 );
  692. temp |= ( ( stat.cb & 0x1 ) << 2 ); /* write one to clear */
  693. temp |= ( ( stat.eosi & 0x1 ) << 1 ); /* write one to clear */
  694. temp |= ( stat.eocai & 0x1 ); /* write one to clear */
  695. store_runtime_reg( eumbbar, dma_reg_tb[LOCAL][channel*NUM_DMA_REG + DMA_SR_REG], temp );
  696. #ifdef DMADBG0
  697. PRINT( "%s(%d): DMA channel %d SR := 0x%08x\n", __FILE__, __LINE__, channel, temp );
  698. #endif
  699. return rval;
  700. }