]> git.ipfire.org Git - people/ms/u-boot.git/blob - cpu/mpc824x/drivers/i2o/i2o1.c
* Code cleanup:
[people/ms/u-boot.git] / 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 }