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