mbgtools-lx  4.2.8
pcpsirq.h
Go to the documentation of this file.
1 
2 /**************************************************************************
3  *
4  * $Id: pcpsirq.h 1.9 2018/09/21 15:41:25 martin TRASH $
5  *
6  * Copyright (c) Meinberg Funkuhren, Bad Pyrmont, Germany
7  *
8  * Description:
9  * OS independent definitions used to handle interrupts from
10  * Meinberg PCI devices.
11  *
12  * -----------------------------------------------------------------------
13  * $Log: pcpsirq.h $
14  * Revision 1.9 2018/09/21 15:41:25 martin
15  * Moved some specific macros here.
16  * Account for renamed I/O macros and symbols.
17  * Revision 1.8 2012/10/15 09:50:44 martin
18  * Account for modified low level macros.
19  * Revision 1.7.1.3 2011/12/20 13:46:07 martin
20  * Conditionally support memory mapped access for MBGPEX cards.
21  * Revision 1.7.1.2 2011/06/29 11:03:28 martin
22  * Updated a comment.
23  * Revision 1.7.1.1 2011/02/09 17:22:36 martin
24  * Revision 1.7 2008/12/05 12:20:36 martin
25  * Protect HW access to enable/disable IRQ by mutex.
26  * Support mapped I/O resources.
27  * Changes due to renamed library macros.
28  * Revision 1.6 2007/07/20 10:16:52 martin
29  * Reworte some IRQ macros.
30  * Moved some AMCC specific definitions to amccdefs.h.
31  * Removed obsolete code.
32  * Revision 1.5 2007/06/06 11:15:27Z martin
33  * Fixed syntax of some macros.
34  * Revision 1.4 2007/03/01 16:15:34Z martin
35  * Use generic port I/O macros.
36  * Revision 1.3 2004/11/09 14:44:21 martin
37  * Use C99 fixed-size data types if required.
38  * Revision 1.2 2003/04/02 07:51:37 martin
39  * Added support for devices with PCI_ASIC.
40  * Revision 1.1 2001/03/28 09:36:43Z MARTIN
41  * Initial revision
42  *
43  **************************************************************************/
44 
45 #ifndef _PCPSIRQ_H
46 #define _PCPSIRQ_H
47 
48 
49 #include <pcpsdrvr.h>
50 #include <amccdefs.h>
51 #include <pci_asic.h>
52 
53 
54 // Each of the macros below expects a parameter _d which is
55 // a pointer to the PCPS_DDEV structure which represents the
56 // hardware device.
57 
58 // The macros below generate code only if MCA support is enabled.
59 
60 #if _PCPS_USE_MCA
61  #define _set_mca_port_bit( _d, _adr, _msk ) \
62  _mbg_outp8( (_d), 0, _adr, _mbg_inp8( (_d), 0, _adr ) | (_msk) )
63 
64  #define _clear_mca_port_bit( _d, _adr, _msk ) \
65  _mbg_outp8( (_d), 0, _adr, _mbg_inp8( (_d), 0, _adr ) & ~(_msk) )
66 
67  #define MCIC_IRQ 0x04
68  #define _mcic_enb_reg( _r ) ( (_r) + 0x0A )
69  #define _mcic_ack_reg( _r ) ( (_r) + 0x0B )
70 
71  // No MCA dependent local variables required, and no
72  // MCA dependent interrupt flag to check.
73 
74  // In ISR function, pass acknowledge to the MCA
75  // interface chip.
76  #define _pcps_ddev_ack_irq_mca( _d ) \
77  if ( _pcps_ddev_is_mca( _d ) ) \
78  { \
79  MBG_IOPORT_ADDR_MAPPED port = _mcic_ack_reg( _pcps_ddev_io_base_mapped( _d, 0 ) ); \
80  _set_mca_port_bit( (_d), port, MCIC_IRQ ); \
81  }
82 
83  // In IRQ init function, enable IRQ on the
84  // interface chip.
85  #define _pcps_ddev_enb_irq_mca( _d ) \
86  if ( _pcps_ddev_is_mca( _d ) ) \
87  { \
88  uint16_t port = _mcic_enb_reg( _pcps_ddev_io_base_mapped( _d, 0 ) ); \
89  set_pos_reg( 4, _pcps_ddev_slot_num( _d ), active_irq.map_code ); \
90  _set_mca_port_bit( (_d), port, MCIC_IRQ ); \
91  }
92 
93  // In IRQ de-init function, disable IRQ on the
94  // interface chip.
95  #define _pcps_ddev_disb_irq_mca( _d ) \
96  if ( _pcps_ddev_is_mca( _d ) ) \
97  { \
98  uint16_t port = _mcic_enb_reg( _pcps_ddev_io_base_mapped( _d, 0 ) ); \
99  _clear_mca_port_bit( (_d), port, MCIC_IRQ ); \
100  }
101 
102 #else
103 
104  // Do nothing if MCA not supported.
105  #define _pcps_ddev_enb_irq_mca( _d ) _nop_macro_fnc()
106  #define _pcps_ddev_disb_irq_mca( _d ) _nop_macro_fnc()
107  #define _pcps_ddev_ack_irq_mca( _d ) _nop_macro_fnc()
108 
109 #endif
110 
111 
112 
113 // The macros below generate code only if PCI support is enabled.
114 
115 #if ( _PCPS_USE_PCI )
116 
117  #if _PCPS_USE_MM_IO
118 
119  // TODO: Take are of endianess
120 
121  #define _mbg_inp32_to_cpu_ex( _d, _i, _p, _r ) \
122  ( _pcps_ddev_access_mode_mm( (_d) ) ? \
123  _mbg_mmrd32_to_cpu( &(_d)->mm_asic_addr->control_status.ul ) : \
124  _mbg_inp32_to_cpu( (_d), (_i), (_p) ) \
125  )
126 
127  #define _mbg_outp32_to_mbg_ex( _d, _i, _p, _r, _v ) \
128  do \
129  { \
130  if ( _pcps_ddev_access_mode_mm( (_d) ) ) \
131  _mbg_mmwr32_to_mbg( &(_d)->mm_asic_addr->control_status.ul, (_v) ); \
132  else \
133  _mbg_outp32_to_mbg( _d, _i, _p, _v ); \
134  } while ( 0 )
135 
136  #else
137 
138  #define _mbg_inp32_to_cpu_ex( _d, _i, _p, _r ) _mbg_inp32_to_cpu( _d, _i, _p )
139  #define _mbg_outp32_to_mbg_ex( _d, _i, _p, _r, _v ) _mbg_outp32_to_mbg( _d, _i, _p, _v )
140 
141  #endif
142 
143 
144  // In ISR function, pass acknowledge to the PCI
145  // interface chip.
146  // 1.) Read PCI incoming mailbox to clear IRQ.
147  // 2.) Clear interrupt source, deassert INTA# signal
148  // and leave interrupt enabled by writing '1's to
149  // the interrupt flag and interrupt enable bits.
150  #define _pcps_ddev_ack_irq_pci( _d ) \
151  if ( (_d)->irq_ack_mask ) \
152  { \
153  if ( _pcps_ddev_is_pci_amcc( _d ) ) \
154  _mbg_inp32_to_cpu( (_d), 0, _pcps_ddev_io_base_mapped( _d, 0 ) \
155  + AMCC_OP_REG_IMB4 ); \
156  \
157  _mbg_outp32_to_mbg_ex( (_d), 0, (_d)->irq_ack_port, control_status, \
158  (_d)->irq_ack_mask ); \
159  }
160 
161  // In IRQ init function, enable IRQ on the
162  // interface chip.
163  #define _pcps_ddev_enb_irq_pci( _d ) \
164  if ( (_d)->irq_enb_mask ) \
165  { \
166  uint32_t intcsr = _mbg_inp32_to_cpu_ex( (_d), 0, \
167  (_d)->irq_enb_disb_port, control_status ); \
168  _mbg_outp32_to_mbg_ex( (_d), 0, (_d)->irq_enb_disb_port, control_status, \
169  intcsr | (_d)->irq_enb_mask ); \
170  }
171 
172  // In IRQ de-init function, disable IRQ on the
173  // interface chip.
174  #define _pcps_ddev_disb_irq_pci( _d ) \
175  if ( (_d)->irq_disb_mask ) \
176  { \
177  uint32_t intcsr = _mbg_inp32_to_cpu_ex( (_d), 0, \
178  (_d)->irq_enb_disb_port, control_status ); \
179  _mbg_outp32_to_mbg_ex( (_d), 0, (_d)->irq_enb_disb_port, control_status, \
180  intcsr & ~(_d)->irq_disb_mask ); \
181  }
182 
183 #else
184  // Do nothing if PCI not supported.
185  #define _pcps_ddev_enb_irq_pci( _d ) _nop_macro_fnc()
186  #define _pcps_ddev_disb_irq_pci( _d ) _nop_macro_fnc()
187  #define _pcps_ddev_ack_irq_pci( _d ) _nop_macro_fnc()
188 #endif
189 
190 
191 
192 // In ISR function, verify that the hardware device has
193 // really generated the current IRQ.
194 // If device is PCI the interface chip's IRQ flag is set.
195 // For non-PCI devices check the IRQ flag of the clock's
196 // status port.
197 #if ( _PCPS_USE_PCI )
198  #define _pcps_ddev_has_gen_irq( _d ) \
199  ( ( (_d)->irq_flag_mask ) ? \
200  ( _mbg_inp32_to_cpu_ex( (_d), 0, (_d)->irq_flag_port, control_status ) & (_d)->irq_flag_mask ) : \
201  ( _pcps_ddev_read_status_port( _d ) & PCPS_ST_IRQF ) \
202  )
203 
204 #else
205  #define _pcps_ddev_has_gen_irq( _d ) \
206  ( _pcps_ddev_read_status_port( _d ) & PCPS_ST_IRQF )
207 #endif
208 
209 
210 // In ISR function, acknowledge IRQ requests to the
211 // hardware device.
212 #define _pcps_ddev_ack_irq( _d ) \
213 { \
214  _pcps_ddev_ack_irq_pci( _d ); \
215  _pcps_ddev_ack_irq_mca( _d ); \
216 }
217 
218 
219 // The macro below should be called at the end of the
220 // interrupt initialization function to instruct the
221 // radio clock hardware to generate IRQs. This code
222 // must be executed after the IRQ service function
223 // has been registered.
224 // The _cmd parameter must be one of the PCPS_IRQ_...
225 // codes defined in pcpsdefs.h which determine the
226 // IRQ rate (per second, per minute, etc.)
227 #define _pcps_ddev_enb_irq( _d, _cmd ) \
228 { \
229  _pcps_sem_inc( _d ); \
230  _pcps_ddev_enb_irq_mca( _d ); \
231  _pcps_ddev_enb_irq_pci( _d ); \
232  _pcps_write_byte( _d, _cmd ); \
233  _pcps_sem_dec( _d ); \
234 }
235 
236 
237 // The macro below should be called at the beginning
238 // of the interrupt deinitialization function to instruct
239 // the radio clock hardware to stop generating IRQs.
240 // This code must be executed before the IRQ service function
241 // is deregistered.
242 #define _pcps_ddev_disb_irq( _d ) \
243 { \
244  _pcps_sem_inc( _d ); \
245  _pcps_write_byte( _d, PCPS_IRQ_NONE ); \
246  _pcps_ddev_disb_irq_mca( _d ); \
247  _pcps_ddev_disb_irq_pci( _d ); \
248  _pcps_sem_dec( _d ); \
249 }
250 
251 
252 #endif /* _PCPSIRQ_H */