i2o1.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. /*********************************************************
  2. * $Id
  3. *
  4. * copyright @ Motorola, 1999
  5. *********************************************************/
  6. #include "i2o.h"
  7. extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg );
  8. #pragma Alias( load_runtime_reg, "load_runtime_reg" );
  9. extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val );
  10. #pragma Alias( store_runtime_reg, "store_runtime_reg" );
  11. typedef struct _fifo_stat
  12. {
  13. QUEUE_SIZE qsz;
  14. unsigned int qba;
  15. } FIFOSTAT;
  16. FIFOSTAT fifo_stat = { QSIZE_4K, 0xffffffff };
  17. /**********************************************************************************
  18. * function: I2OMsgEnable
  19. *
  20. * description: Enable the interrupt associated with in/out bound msg
  21. * return I2OSUCCESS if no error, otherwise return I2OMSGINVALID.
  22. *
  23. * All previously enabled interrupts are preserved.
  24. * note:
  25. * Inbound message interrupt generated by PCI master and serviced by local processor
  26. * Outbound message interrupt generated by local processor and serviced by PCI master
  27. *
  28. * local processor needs to enable its inbound interrupts it wants to handle(LOCAL)
  29. * PCI master needs to enable the outbound interrupts of devices it wants to handle(REMOTE)
  30. ************************************************************************************/
  31. I2OSTATUS I2OMsgEnable ( LOCATION loc, /* REMOTE/LOCAL */
  32. unsigned int base, /* pcsrbar/eumbbar */
  33. unsigned char n ) /* b'1' - msg 0
  34. * b'10'- msg 1
  35. * b'11'- both
  36. */
  37. {
  38. unsigned int reg, val;
  39. if ( ( n & 0x3 ) == 0 )
  40. {
  41. /* neither msg 0, nor msg 1 */
  42. return I2OMSGINVALID;
  43. }
  44. n = (~n) & 0x3;
  45. /* LOCATION - REMOTE : enable outbound message of device, pcsrbar as base
  46. * LOCAL : enable local inbound message, eumbbar as base
  47. */
  48. reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
  49. val = load_runtime_reg( base, reg );
  50. val &= 0xfffffffc; /* masked out the msg interrupt bits */
  51. val |= n; /* LSB are the one we want */
  52. store_runtime_reg( base, reg, val );
  53. return I2OSUCCESS;
  54. }
  55. /*********************************************************************************
  56. * function: I2OMsgDisable
  57. *
  58. * description: Disable the interrupt associated with in/out bound msg
  59. * Other previously enabled interrupts are preserved.
  60. * return I2OSUCCESS if no error otherwise return I2OMSGINVALID
  61. *
  62. * note:
  63. * local processor needs to disable its inbound interrupts it is not interested(LOCAL)
  64. * PCI master needs to disable outbound interrupts of devices it is not interested(REMOTE)
  65. *********************************************************************************/
  66. I2OSTATUS I2OMsgDisable( LOCATION loc, /* REMOTE/LOCAL */
  67. unsigned int base, /* pcsrbar/eumbbar */
  68. unsigned char n ) /* b'1' - msg 0
  69. * b'10'- msg 1
  70. * b'11'- both
  71. */
  72. {
  73. unsigned int reg, val;
  74. if ( ( n & 0x3 ) == 0 )
  75. {
  76. /* neither msg 0, nor msg 1 */
  77. return I2OMSGINVALID;
  78. }
  79. /* LOCATION - REMOTE : disable outbound message interrupt of device, pcsrbar as base
  80. * LOCAL : disable local inbound message interrupt, eumbbar as base
  81. */
  82. reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
  83. val = load_runtime_reg( base, reg );
  84. val &= 0xfffffffc; /* masked out the msg interrupt bits */
  85. val |= ( n & 0x3 );
  86. store_runtime_reg( base, reg, val );
  87. return I2OSUCCESS;
  88. }
  89. /**************************************************************************
  90. * function: I2OMsgGet
  91. *
  92. * description: Local processor reads the nth Msg register from its inbound msg,
  93. * or a PCI Master reads nth outbound msg from device
  94. *
  95. * return I2OSUCCESS if no error, otherwise return I2OMSGINVALID.
  96. *
  97. * note:
  98. * If it is not local, pcsrbar must be passed to the function. Otherwise eumbbar is passed.
  99. * If it is remote, outbound msg on the device is read; otherwise local inbound msg is read
  100. *************************************************************************/
  101. I2OSTATUS I2OMsgGet ( LOCATION loc, /* REMOTE/LOCAL */
  102. unsigned int base, /*pcsrbar/eumbbar */
  103. unsigned int n, /* 0 or 1 */
  104. unsigned int *msg )
  105. {
  106. if ( n >= I2O_NUM_MSG || msg == 0 )
  107. {
  108. return I2OMSGINVALID;
  109. }
  110. if ( loc == REMOTE )
  111. {
  112. /* read the outbound msg of the device, pcsrbar as base */
  113. *msg = load_runtime_reg( base, I2O_OMR0+n*I2O_REG_OFFSET );
  114. }
  115. else
  116. {
  117. /* read the inbound msg sent by PCI master, eumbbar as base */
  118. *msg = load_runtime_reg( base, I2O_IMR0+n*I2O_REG_OFFSET );
  119. }
  120. return I2OSUCCESS;
  121. }
  122. /***************************************************************
  123. * function: I2OMsgPost
  124. *
  125. * description: Kahlua writes to its nth outbound msg register
  126. * PCI master writes to nth inbound msg register of device
  127. *
  128. * return I2OSUCCESS if no error, otherwise return I2OMSGINVALID.
  129. *
  130. * note:
  131. * If it is not local, pcsrbar must be passed to the function. Otherwise eumbbar is passed.
  132. *
  133. * If it is remote, inbound msg on the device is written; otherwise local outbound msg is written
  134. ***************************************************************/
  135. I2OSTATUS I2OMsgPost( LOCATION loc, /* REMOTE/LOCAL */
  136. unsigned int base, /*pcsrbar/eumbbar */
  137. unsigned int n, /* 0 or 1 */
  138. unsigned int msg )
  139. {
  140. if ( n >= I2O_NUM_MSG )
  141. {
  142. return I2OMSGINVALID;
  143. }
  144. if ( loc == REMOTE )
  145. {
  146. /* write to the inbound msg register of the device, pcsrbar as base */
  147. store_runtime_reg( base, I2O_IMR0+n*I2O_REG_OFFSET, msg );
  148. }
  149. else
  150. {
  151. /* write to the outbound msg register for PCI master to read, eumbbar as base */
  152. store_runtime_reg( base, I2O_OMR0+n*I2O_REG_OFFSET, msg );
  153. }
  154. return I2OSUCCESS;
  155. }
  156. /***********************************************************************
  157. * function: I2ODBEnable
  158. *
  159. * description: Local processor enables it's inbound doorbell interrupt
  160. * PCI master enables outbound doorbell interrupt of devices
  161. * Other previously enabled interrupts are preserved.
  162. * Return I2OSUCCESS if no error otherwise return I2ODBINVALID
  163. *
  164. * note:
  165. * In DoorBell interrupt is generated by PCI master and serviced by local processor
  166. * Out Doorbell interrupt is generated by local processor and serviced by PCI master
  167. *
  168. * Out Doorbell interrupt is generated by local processor and serviced by PCI master
  169. * PCI master needs to enable the outbound doorbell interrupts of device it wants to handle
  170. **********************************************************************/
  171. I2OSTATUS I2ODBEnable( LOCATION loc, /* REMOTE/LOCAL */
  172. unsigned int base, /* pcsrbar/eumbbar */
  173. unsigned int in_db ) /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
  174. {
  175. /* LOCATION - REMOTE : PCI master initializes outbound doorbell message of device
  176. * LOCAL : Kahlua initializes its inbound doorbell message
  177. */
  178. unsigned int val;
  179. if ( loc == LOCAL && ( in_db & 0x3 ) == 0 )
  180. {
  181. return I2ODBINVALID;
  182. }
  183. if ( loc == REMOTE )
  184. {
  185. /* pcsrbar is base */
  186. val = load_runtime_reg( base, I2O_OMIMR );
  187. val &= 0xfffffff7;
  188. store_runtime_reg( base, I2O_OMIMR , val );
  189. }
  190. else
  191. {
  192. /* eumbbar is base */
  193. val = load_runtime_reg( base, I2O_IMIMR);
  194. in_db = ( (~in_db) & 0x3 ) << 3;
  195. val = ( val & 0xffffffe7) | in_db;
  196. store_runtime_reg( base, I2O_IMIMR, val );
  197. }
  198. return I2OSUCCESS;
  199. }
  200. /**********************************************************************************
  201. * function: I2ODBDisable
  202. *
  203. * description: local processor disables its inbound DoorBell Interrupt
  204. * PCI master disables outbound DoorBell interrupt of device
  205. * Other previously enabled interrupts are preserved.
  206. * return I2OSUCCESS if no error.Otherwise return I2ODBINVALID
  207. *
  208. * note:
  209. * local processor needs to disable its inbound doorbell interrupts it is not interested
  210. *
  211. * PCI master needs to disable outbound doorbell interrupts of device it is not interested
  212. ************************************************************************************/
  213. I2OSTATUS I2ODBDisable( LOCATION loc, /* REMOTE/LOCAL */
  214. unsigned int base, /* pcsrbar/eumbbar */
  215. unsigned int in_db ) /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
  216. {
  217. /* LOCATION - REMOTE : handle device's out bound message initialization
  218. * LOCAL : handle local in bound message initialization
  219. */
  220. unsigned int val;
  221. if ( loc == LOCAL && ( in_db & 0x3 ) == 0 )
  222. {
  223. return I2ODBINVALID;
  224. }
  225. if ( loc == REMOTE )
  226. {
  227. /* pcsrbar is the base */
  228. val = load_runtime_reg( base, I2O_OMIMR );
  229. val |= 0x8;
  230. store_runtime_reg( base, I2O_OMIMR, val );
  231. }
  232. else
  233. {
  234. val = load_runtime_reg( base, I2O_IMIMR);
  235. in_db = ( in_db & 0x3 ) << 3;
  236. val |= in_db;
  237. store_runtime_reg( base, I2O_IMIMR, val );
  238. }
  239. return I2OSUCCESS;
  240. }
  241. /**********************************************************************************
  242. * function: I2ODBGet
  243. *
  244. * description: Local processor reads its in doorbell register,
  245. * PCI master reads the outdoorbell register of device.
  246. * After a doorbell register is read, the whole register will be cleared.
  247. * Otherwise, HW keeps generating interrupt.
  248. *
  249. * note:
  250. * If it is not local, pcsrbar must be passed to the function.
  251. * Otherwise eumbbar is passed.
  252. *
  253. * If it is remote, out doorbell register on the device is read.
  254. * Otherwise local in doorbell is read
  255. *
  256. * If the register is not cleared by write to it, any remaining bit of b'1's
  257. * will cause interrupt pending.
  258. *********************************************************************************/
  259. unsigned int I2ODBGet( LOCATION loc, /* REMOTE/LOCAL */
  260. unsigned int base) /* pcsrbar/eumbbar */
  261. {
  262. unsigned int msg, val;
  263. if ( loc == REMOTE )
  264. {
  265. /* read outbound doorbell register of device, pcsrbar is the base */
  266. val = load_runtime_reg( base, I2O_ODBR );
  267. msg = val & 0xe0000000;
  268. store_runtime_reg( base, I2O_ODBR, val ); /* clear the register */
  269. }
  270. else
  271. {
  272. /* read the inbound doorbell register, eumbbar is the base */
  273. val = load_runtime_reg( base, I2O_IDBR );
  274. store_runtime_reg( base, I2O_IDBR, val ); /* clear the register */
  275. msg = val;
  276. }
  277. return msg;
  278. }
  279. /**********************************************************************
  280. * function: I2ODBPost
  281. *
  282. * description: local processor writes to a outbound doorbell register,
  283. * PCI master writes to the inbound doorbell register of device
  284. *
  285. * note:
  286. * If it is not local, pcsrbar must be passed to the function.
  287. * Otherwise eumbbar is passed.
  288. *
  289. * If it is remote, in doorbell register on the device is written.
  290. * Otherwise local out doorbell is written
  291. *********************************************************************/
  292. void I2ODBPost( LOCATION loc, /* REMOTE/LOCAL */
  293. unsigned int base, /* pcsrbar/eumbbar */
  294. unsigned int msg ) /* in / out */
  295. {
  296. if ( loc == REMOTE )
  297. {
  298. /* write to inbound doorbell register of device, pcsrbar is the base */
  299. store_runtime_reg( base, I2O_IDBR, msg );
  300. }
  301. else
  302. {
  303. /* write to local outbound doorbell register, eumbbar is the base */
  304. store_runtime_reg( base, I2O_ODBR, msg & 0x1fffffff );
  305. }
  306. }
  307. /********************************************************************
  308. * function: I2OOutMsgStatGet
  309. *
  310. * description: PCI master reads device's outbound msg unit interrupt status.
  311. * Reading an interrupt status register,
  312. * the register will be cleared.
  313. *
  314. * The value of the status register is AND with the outbound
  315. * interrupt mask and result is returned.
  316. *
  317. * note:
  318. * pcsrbar must be passed to the function.
  319. ********************************************************************/
  320. I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT *val )
  321. {
  322. unsigned int stat;
  323. unsigned int mask;
  324. if ( val == 0 )
  325. {
  326. return I2OINVALID;
  327. }
  328. /* read device's outbound status */
  329. stat = load_runtime_reg( pcsrbar, I2O_OMISR );
  330. mask = load_runtime_reg( pcsrbar, I2O_OMIMR );
  331. store_runtime_reg( pcsrbar, I2O_OMISR, stat & 0xffffffd7);
  332. stat &= mask;
  333. val->rsvd0 = ( stat & 0xffffffc0 ) >> 6;
  334. val->opqi = ( stat & 0x00000020 ) >> 5;
  335. val->rsvd1 = ( stat & 0x00000010 ) >> 4;
  336. val->odi = ( stat & 0x00000008 ) >> 3;
  337. val->rsvd2 = ( stat & 0x00000004 ) >> 2;
  338. val->om1i = ( stat & 0x00000002 ) >> 1;
  339. val->om0i = ( stat & 0x00000001 );
  340. return I2OSUCCESS;
  341. }
  342. /********************************************************************
  343. * function: I2OInMsgStatGet
  344. *
  345. * description: Local processor reads its inbound msg unit interrupt status.
  346. * Reading an interrupt status register,
  347. * the register will be cleared.
  348. *
  349. * The inbound msg interrupt status is AND with the inbound
  350. * msg interrupt mask and result is returned.
  351. *
  352. * note:
  353. * eumbbar must be passed to the function.
  354. ********************************************************************/
  355. I2OSTATUS I2OInMsgStatGet(unsigned int eumbbar, I2OIMSTAT *val)
  356. {
  357. unsigned int stat;
  358. unsigned int mask;
  359. if ( val == 0 )
  360. {
  361. return I2OINVALID;
  362. }
  363. /* read device's outbound status */
  364. stat = load_runtime_reg( eumbbar, I2O_OMISR );
  365. mask = load_runtime_reg( eumbbar, I2O_OMIMR );
  366. store_runtime_reg( eumbbar, I2O_OMISR, stat & 0xffffffe7 );
  367. stat &= mask;
  368. val->rsvd0 = ( stat & 0xfffffe00 ) >> 9;
  369. val->ofoi = ( stat & 0x00000100 ) >> 8;
  370. val->ipoi = ( stat & 0x00000080 ) >> 7;
  371. val->rsvd1 = ( stat & 0x00000040 ) >> 6;
  372. val->ipqi = ( stat & 0x00000020 ) >> 5;
  373. val->mci = ( stat & 0x00000010 ) >> 4;
  374. val->idi = ( stat & 0x00000008 ) >> 3;
  375. val->rsvd2 = ( stat & 0x00000004 ) >> 2;
  376. val->im1i = ( stat & 0x00000002 ) >> 1;
  377. val->im0i = ( stat & 0x00000001 );
  378. return I2OSUCCESS;
  379. }
  380. /***********************************************************
  381. * function: I2OFIFOInit
  382. *
  383. * description: Configure the I2O FIFO, including QBAR,
  384. * IFHPR/IFTPR, IPHPR/IPTPR, OFHPR/OFTPR,
  385. * OPHPR/OPTPR, MUCR.
  386. *
  387. * return I2OSUCCESS if no error,
  388. * otherwise return I2OQUEINVALID
  389. *
  390. * note: It is NOT this driver's responsibility of initializing
  391. * MFA blocks, i.e., FIFO queue itself. The MFA blocks
  392. * must be initialized before I2O unit can be used.
  393. ***********************************************************/
  394. I2OSTATUS I2OFIFOInit( unsigned int eumbbar,
  395. QUEUE_SIZE sz, /* value of CQS of MUCR */
  396. unsigned int qba) /* queue base address that must be aligned at 1M */
  397. {
  398. if ( ( qba & 0xfffff ) != 0 )
  399. {
  400. /* QBA must be aligned at 1Mbyte boundary */
  401. return I2OQUEINVALID;
  402. }
  403. store_runtime_reg( eumbbar, I2O_QBAR, qba );
  404. store_runtime_reg( eumbbar, I2O_MUCR, (unsigned int)sz );
  405. store_runtime_reg( eumbbar, I2O_IFHPR, qba );
  406. store_runtime_reg( eumbbar, I2O_IFTPR, qba );
  407. store_runtime_reg( eumbbar, I2O_IPHPR, qba + 1 * ( sz << 11 ));
  408. store_runtime_reg( eumbbar, I2O_IPTPR, qba + 1 * ( sz << 11 ));
  409. store_runtime_reg( eumbbar, I2O_OFHPR, qba + 2 * ( sz << 11 ));
  410. store_runtime_reg( eumbbar, I2O_OFTPR, qba + 2 * ( sz << 11 ));
  411. store_runtime_reg( eumbbar, I2O_OPHPR, qba + 3 * ( sz << 11 ));
  412. store_runtime_reg( eumbbar, I2O_OPTPR, qba + 3 * ( sz << 11 ));
  413. fifo_stat.qsz = sz;
  414. fifo_stat.qba = qba;
  415. return I2OSUCCESS;
  416. }
  417. /**************************************************
  418. * function: I2OFIFOEnable
  419. *
  420. * description: Enable the circular queue
  421. * return I2OSUCCESS if no error.
  422. * Otherwise I2OQUEINVALID is returned.
  423. *
  424. * note:
  425. *************************************************/
  426. I2OSTATUS I2OFIFOEnable( unsigned int eumbbar )
  427. {
  428. unsigned int val;
  429. if ( fifo_stat.qba == 0xfffffff )
  430. {
  431. return I2OQUEINVALID;
  432. }
  433. val = load_runtime_reg( eumbbar, I2O_MUCR );
  434. store_runtime_reg( eumbbar, I2O_MUCR, val | 0x1 );
  435. return I2OSUCCESS;
  436. }
  437. /**************************************************
  438. * function: I2OFIFODisable
  439. *
  440. * description: Disable the circular queue
  441. *
  442. * note:
  443. *************************************************/
  444. void I2OFIFODisable( unsigned int eumbbar )
  445. {
  446. if ( fifo_stat.qba == 0xffffffff )
  447. {
  448. /* not enabled */
  449. return;
  450. }
  451. unsigned int val = load_runtime_reg( eumbbar, I2O_MUCR );
  452. store_runtime_reg( eumbbar, I2O_MUCR, val & 0xfffffffe );
  453. }
  454. /****************************************************
  455. * function: I2OFIFOAlloc
  456. *
  457. * description: Allocate a free MFA from free FIFO.
  458. * return I2OSUCCESS if no error.
  459. * return I2OQUEEMPTY if no more free MFA.
  460. * return I2OINVALID on other errors.
  461. *
  462. * A free MFA must be allocated before a
  463. * message can be posted.
  464. *
  465. * note:
  466. * PCI Master allocates a free MFA from inbound queue of device
  467. * (pcsrbar is the base,) through the inbound queue port of device
  468. * while local processor allocates a free MFA from its outbound
  469. * queue (eumbbar is the base.)
  470. *
  471. ****************************************************/
  472. I2OSTATUS I2OFIFOAlloc( LOCATION loc,
  473. unsigned int base,
  474. void **pMsg )
  475. {
  476. I2OSTATUS stat = I2OSUCCESS;
  477. void *pHdr, *pTil;
  478. if ( pMsg == 0 || *pMsg == 0 || fifo_stat.qba == 0xffffffff )
  479. {
  480. /* not configured */
  481. return I2OQUEINVALID;
  482. }
  483. if ( loc == REMOTE )
  484. {
  485. /* pcsrbar is the base and read the inbound free tail ptr */
  486. pTil = (void *)load_runtime_reg( base, I2O_IFQPR );
  487. if ( ( (unsigned int)pTil & 0xFFFFFFF ) == 0xFFFFFFFF )
  488. {
  489. stat = I2OQUEEMPTY;
  490. }
  491. else
  492. {
  493. *pMsg = pTil;
  494. }
  495. }
  496. else
  497. {
  498. /* eumbbar is the base and read the outbound free tail ptr */
  499. pHdr = (void *)load_runtime_reg( base, I2O_OFHPR ); /* queue head */
  500. pTil = (void *)load_runtime_reg( base, I2O_OFTPR ); /* queue tail */
  501. /* check underflow */
  502. if ( pHdr == pTil )
  503. {
  504. /* hdr and til point to the same fifo item, no free MFA */
  505. stat = I2OQUEEMPTY;
  506. }
  507. else
  508. {
  509. /* update OFTPR */
  510. *pMsg = (void *)(*(unsigned char *)pTil);
  511. pTil = (void *)((unsigned int)pTil + 4);
  512. if ( (unsigned int)pTil == fifo_stat.qba + ( 4 * ( fifo_stat.qsz << 11 ) ) )
  513. {
  514. /* reach the upper limit */
  515. pTil = (void *)(fifo_stat.qba + ( 3 * (fifo_stat.qsz << 11) ));
  516. }
  517. store_runtime_reg( base, I2O_OFTPR, (unsigned int)pTil );
  518. }
  519. }
  520. return stat;
  521. }
  522. /******************************************************
  523. * function: I2OFIFOFree
  524. *
  525. * description: Free a used MFA back to free queue after
  526. * use.
  527. * return I2OSUCCESS if no error.
  528. * return I2OQUEFULL if inbound free queue
  529. * overflow
  530. *
  531. * note: PCI Master frees a MFA into device's outbound queue
  532. * (OFQPR) while local processor frees a MFA into its
  533. * inbound queue (IFHPR).
  534. *****************************************************/
  535. I2OSTATUS I2OFIFOFree( LOCATION loc,
  536. unsigned int base,
  537. void *pMsg )
  538. {
  539. void **pHdr, **pTil;
  540. I2OSTATUS stat = I2OSUCCESS;
  541. if ( fifo_stat.qba == 0xffffffff || pMsg == 0 )
  542. {
  543. return I2OQUEINVALID;
  544. }
  545. if ( loc == REMOTE )
  546. {
  547. /* pcsrbar is the base */
  548. store_runtime_reg( base, I2O_OFQPR, (unsigned int)pMsg );
  549. }
  550. else
  551. {
  552. /* eumbbar is the base */
  553. pHdr = (void **)load_runtime_reg( base, I2O_IFHPR );
  554. pTil = (void **)load_runtime_reg( base, I2O_IFTPR );
  555. /* store MFA */
  556. *pHdr = pMsg;
  557. /* update IFHPR */
  558. pHdr += 4;
  559. if ( (unsigned int)pHdr == fifo_stat.qba + ( fifo_stat.qsz << 11 ) )
  560. {
  561. /* reach the upper limit */
  562. pHdr = (void **)fifo_stat.qba;
  563. }
  564. /* check inbound free queue overflow */
  565. if ( pHdr != pTil )
  566. {
  567. store_runtime_reg( base, I2O_OPHPR, (unsigned int)pHdr);
  568. }
  569. else
  570. {
  571. stat = I2OQUEFULL;
  572. }
  573. }
  574. return stat;
  575. }
  576. /*********************************************
  577. * function: I2OFIFOPost
  578. *
  579. * description: Post a msg into FIFO post queue
  580. * the value of msg must be the one
  581. * returned by I2OFIFOAlloc
  582. *
  583. * note: PCI Master posts a msg into device's inbound queue
  584. * (IFQPR) while local processor post a msg into device's
  585. * outbound queue (OPHPR)
  586. *********************************************/
  587. I2OSTATUS I2OFIFOPost( LOCATION loc,
  588. unsigned int base,
  589. void *pMsg )
  590. {
  591. void **pHdr, **pTil;
  592. I2OSTATUS stat = I2OSUCCESS;
  593. if ( fifo_stat.qba == 0xffffffff || pMsg == 0 )
  594. {
  595. return I2OQUEINVALID;
  596. }
  597. if ( loc == REMOTE )
  598. {
  599. /* pcsrbar is the base */
  600. store_runtime_reg( base, I2O_IFQPR, (unsigned int)pMsg );
  601. }
  602. else
  603. {
  604. /* eumbbar is the base */
  605. pHdr = (void **)load_runtime_reg( base, I2O_OPHPR );
  606. pTil = (void **)load_runtime_reg( base, I2O_OPTPR );
  607. /* store MFA */
  608. *pHdr = pMsg;
  609. /* update IFHPR */
  610. pHdr += 4;
  611. if ( (unsigned int)pHdr == fifo_stat.qba + 3 * ( fifo_stat.qsz << 11 ) )
  612. {
  613. /* reach the upper limit */
  614. pHdr = (void **)(fifo_stat.qba + 2 * ( fifo_stat.qsz << 11 ) );
  615. }
  616. /* check post queue overflow */
  617. if ( pHdr != pTil )
  618. {
  619. store_runtime_reg( base, I2O_OPHPR, (unsigned int)pHdr);
  620. }
  621. else
  622. {
  623. stat = I2OQUEFULL;
  624. }
  625. }
  626. return stat;
  627. }
  628. /************************************************
  629. * function: I2OFIFOGet
  630. *
  631. * description: Read a msg from FIFO
  632. * This function should be called
  633. * only when there is a corresponding
  634. * msg interrupt.
  635. *
  636. * note: PCI Master reads a msg from device's outbound queue
  637. * (OFQPR) while local processor reads a msg from device's
  638. * inbound queue (IPTPR)
  639. ************************************************/
  640. I2OSTATUS I2OFIFOGet( LOCATION loc,
  641. unsigned int base,
  642. void **pMsg )
  643. {
  644. I2OSTATUS stat = I2OSUCCESS;
  645. void *pHdr, *pTil;
  646. if ( pMsg == 0 || *pMsg == 0 || fifo_stat.qba == 0xffffffff )
  647. {
  648. /* not configured */
  649. return I2OQUEINVALID;
  650. }
  651. if ( loc == REMOTE )
  652. {
  653. /* pcsrbar is the base */
  654. pTil = (void *)load_runtime_reg( base, I2O_OFQPR );
  655. if ( ( (unsigned int)pTil & 0xFFFFFFF ) == 0xFFFFFFFF )
  656. {
  657. stat = I2OQUEEMPTY;
  658. }
  659. else
  660. {
  661. *pMsg = pTil;
  662. }
  663. }
  664. else
  665. {
  666. /* eumbbar is the base and read the outbound free tail ptr */
  667. pHdr = (void *)load_runtime_reg( base, I2O_IPHPR ); /* queue head */
  668. pTil = (void *)load_runtime_reg( base, I2O_IPTPR ); /* queue tail */
  669. /* check underflow */
  670. if ( pHdr == pTil )
  671. {
  672. /* no free MFA */
  673. stat = I2OQUEEMPTY;
  674. }
  675. else
  676. {
  677. /* update OFTPR */
  678. *pMsg = (void *)(*(unsigned char *)pTil);
  679. pTil = (void *)((unsigned int)pTil + 4);
  680. if ( (unsigned int)pTil == fifo_stat.qba + 2 * ( fifo_stat.qsz << 11 ) )
  681. {
  682. /* reach the upper limit */
  683. pTil = (void *)(fifo_stat.qba + 1 * (fifo_stat.qsz << 11) );
  684. }
  685. store_runtime_reg( base, I2O_IPTPR, (unsigned int)pTil );
  686. }
  687. }
  688. return stat;
  689. }
  690. /********************************************************
  691. * function: I2OIOP
  692. *
  693. * description: Get the I2O PCI configuration identification
  694. * register.
  695. *
  696. * note: PCI master should pass pcsrbar while local processor
  697. * should pass eumbbar.
  698. *********************************************************/
  699. I2OSTATUS I2OPCIConfigGet( LOCATION loc,
  700. unsigned int base,
  701. I2OIOP * val)
  702. {
  703. unsigned int tmp;
  704. if ( val == 0 )
  705. {
  706. return I2OINVALID;
  707. }
  708. tmp = load_runtime_reg( base, PCI_CFG_CLA );
  709. val->base_class = ( tmp & 0xFF) << 16;
  710. tmp = load_runtime_reg( base, PCI_CFG_SCL );
  711. val->sub_class= ( (tmp & 0xFF) << 8 );
  712. tmp = load_runtime_reg( base, PCI_CFG_PIC );
  713. val->prg_code = (tmp & 0xFF);
  714. return I2OSUCCESS;
  715. }
  716. /*********************************************************
  717. * function: I2OFIFOIntEnable
  718. *
  719. * description: Enable the circular post queue interrupt
  720. *
  721. * note:
  722. * PCI master enables outbound FIFO interrupt of device
  723. * pscrbar is the base
  724. * Device enables its inbound FIFO interrupt
  725. * eumbbar is the base
  726. *******************************************************/
  727. void I2OFIFOIntEnable( LOCATION loc, unsigned int base )
  728. {
  729. unsigned int reg, val;
  730. /* LOCATION - REMOTE : enable outbound message of device, pcsrbar as base
  731. * LOCAL : enable local inbound message, eumbbar as base
  732. */
  733. reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
  734. val = load_runtime_reg( base, reg );
  735. val &= 0xffffffdf; /* clear the msg interrupt bits */
  736. store_runtime_reg( base, reg, val );
  737. }
  738. /****************************************************
  739. * function: I2OFIFOIntDisable
  740. *
  741. * description: Disable the circular post queue interrupt
  742. *
  743. * note:
  744. * PCI master disables outbound FIFO interrupt of device
  745. * (pscrbar is the base)
  746. * Device disables its inbound FIFO interrupt
  747. * (eumbbar is the base)
  748. *****************************************************/
  749. void I2OFIFOIntDisable( LOCATION loc, unsigned int base )
  750. {
  751. /* LOCATION - REMOTE : disable outbound message interrupt of device, pcsrbar as base
  752. * LOCAL : disable local inbound message interrupt, eumbbar as base
  753. */
  754. unsigned int reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
  755. unsigned int val = load_runtime_reg( base, reg );
  756. val |= 0x00000020; /* masked out the msg interrupt bits */
  757. store_runtime_reg( base, reg, val );
  758. }
  759. /*********************************************************
  760. * function: I2OFIFOOverflowIntEnable
  761. *
  762. * description: Enable the circular queue overflow interrupt
  763. *
  764. * note:
  765. * Device enables its inbound FIFO post overflow interrupt
  766. * and outbound free overflow interrupt.
  767. * eumbbar is the base
  768. *******************************************************/
  769. void I2OFIFOOverflowIntEnable( unsigned int eumbbar )
  770. {
  771. unsigned int val = load_runtime_reg( eumbbar, I2O_IMIMR );
  772. val &= 0xfffffe7f; /* clear the two overflow interrupt bits */
  773. store_runtime_reg( eumbbar, I2O_IMIMR, val );
  774. }
  775. /****************************************************
  776. * function: I2OFIFOOverflowIntDisable
  777. *
  778. * description: Disable the circular queue overflow interrupt
  779. *
  780. * note:
  781. * Device disables its inbound post FIFO overflow interrupt
  782. * and outbound free FIFO overflow interrupt
  783. * (eumbbar is the base)
  784. *****************************************************/
  785. void I2OFIFOOverflowIntDisable( unsigned int eumbbar )
  786. {
  787. unsigned int val = load_runtime_reg( eumbbar, I2O_IMIMR );
  788. val |= 0x00000180; /* masked out the msg overflow interrupt bits */
  789. store_runtime_reg( eumbbar, I2O_IMIMR, val );
  790. }