1 | /* Driver for the Tundra Tsi148 pci-vme bridge */ |
---|
2 | |
---|
3 | /* |
---|
4 | * Authorship |
---|
5 | * ---------- |
---|
6 | * This software was created by |
---|
7 | * Till Straumann <strauman@slac.stanford.edu>, 2005-2007, |
---|
8 | * Stanford Linear Accelerator Center, Stanford University. |
---|
9 | * |
---|
10 | * Acknowledgement of sponsorship |
---|
11 | * ------------------------------ |
---|
12 | * This software was produced by |
---|
13 | * the Stanford Linear Accelerator Center, Stanford University, |
---|
14 | * under Contract DE-AC03-76SFO0515 with the Department of Energy. |
---|
15 | * |
---|
16 | * Government disclaimer of liability |
---|
17 | * ---------------------------------- |
---|
18 | * Neither the United States nor the United States Department of Energy, |
---|
19 | * nor any of their employees, makes any warranty, express or implied, or |
---|
20 | * assumes any legal liability or responsibility for the accuracy, |
---|
21 | * completeness, or usefulness of any data, apparatus, product, or process |
---|
22 | * disclosed, or represents that its use would not infringe privately owned |
---|
23 | * rights. |
---|
24 | * |
---|
25 | * Stanford disclaimer of liability |
---|
26 | * -------------------------------- |
---|
27 | * Stanford University makes no representations or warranties, express or |
---|
28 | * implied, nor assumes any liability for the use of this software. |
---|
29 | * |
---|
30 | * Stanford disclaimer of copyright |
---|
31 | * -------------------------------- |
---|
32 | * Stanford University, owner of the copyright, hereby disclaims its |
---|
33 | * copyright and all other rights in this software. Hence, anyone may |
---|
34 | * freely use it for any purpose without restriction. |
---|
35 | * |
---|
36 | * Maintenance of notices |
---|
37 | * ---------------------- |
---|
38 | * In the interest of clarity regarding the origin and status of this |
---|
39 | * SLAC software, this and all the preceding Stanford University notices |
---|
40 | * are to remain affixed to any copy or derivative of this software made |
---|
41 | * or distributed by the recipient and are to be affixed to any copy of |
---|
42 | * software made or distributed by the recipient that contains a copy or |
---|
43 | * derivative of this software. |
---|
44 | * |
---|
45 | * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 |
---|
46 | */ |
---|
47 | |
---|
48 | #include <rtems.h> |
---|
49 | #include <stdio.h> |
---|
50 | #include <stdarg.h> |
---|
51 | #include <bsp/irq.h> |
---|
52 | #include <stdlib.h> |
---|
53 | #include <rtems/bspIo.h> /* printk */ |
---|
54 | #include <rtems/error.h> /* printk */ |
---|
55 | #include <rtems/pci.h> |
---|
56 | #include <bsp.h> |
---|
57 | #include <libcpu/byteorder.h> |
---|
58 | |
---|
59 | #define __INSIDE_RTEMS_BSP__ |
---|
60 | #define _VME_TSI148_DECLARE_SHOW_ROUTINES |
---|
61 | |
---|
62 | #include <bsp/vmeTsi148.h> |
---|
63 | #include <bsp/VMEDMA.h> |
---|
64 | #include <bsp/vmeTsi148DMA.h> |
---|
65 | #include "bspVmeDmaListP.h" |
---|
66 | |
---|
67 | |
---|
68 | #define DEBUG |
---|
69 | |
---|
70 | #ifdef DEBUG |
---|
71 | #define STATIC |
---|
72 | #else |
---|
73 | #define STATIC static |
---|
74 | #endif |
---|
75 | |
---|
76 | /* The tsi has 4 'local' wires that can be hooked to a PIC */ |
---|
77 | |
---|
78 | #define TSI_NUM_WIRES 4 |
---|
79 | |
---|
80 | #define TSI148_NUM_OPORTS 8 /* number of outbound ports */ |
---|
81 | #define TSI148_NUM_IPORTS 8 /* number of inbound ports */ |
---|
82 | |
---|
83 | #define NUM_TSI_DEVS 2 /* number of instances supported */ |
---|
84 | |
---|
85 | #define PCI_VENDOR_TUNDRA 0x10e3 |
---|
86 | #define PCI_DEVICE_TSI148 0x0148 |
---|
87 | |
---|
88 | #define TSI_OTSAU_SPACING 0x020 |
---|
89 | |
---|
90 | #define TSI_OTSAU0_REG 0x100 |
---|
91 | #define TSI_OTSAL0_REG 0x104 |
---|
92 | #define TSI_OTEAU0_REG 0x108 |
---|
93 | #define TSI_OTEAL0_REG 0x10c |
---|
94 | #define TSI_OTOFU0_REG 0x110 |
---|
95 | #define TSI_OTOFL0_REG 0x114 |
---|
96 | #define TSI_OTBS0_REG 0x118 /* 2eSST broadcast select */ |
---|
97 | #define TSI_OTAT0_REG 0x11c |
---|
98 | #define TSI_OTSAU_REG(port) (TSI_OTSAU0_REG + ((port)<<5)) |
---|
99 | #define TSI_OTSAL_REG(port) (TSI_OTSAL0_REG + ((port)<<5)) |
---|
100 | #define TSI_OTEAU_REG(port) (TSI_OTEAU0_REG + ((port)<<5)) |
---|
101 | #define TSI_OTEAL_REG(port) (TSI_OTEAL0_REG + ((port)<<5)) |
---|
102 | #define TSI_OTOFU_REG(port) (TSI_OTOFU0_REG + ((port)<<5)) |
---|
103 | #define TSI_OTOFL_REG(port) (TSI_OTOFL0_REG + ((port)<<5)) |
---|
104 | #define TSI_OTBS_REG(port) (TSI_OTBS0_REG + ((port)<<5)) |
---|
105 | #define TSI_OTAT_REG(port) (TSI_OTAT0_REG + ((port)<<5)) |
---|
106 | # define TSI_OTAT_EN (1<<31) |
---|
107 | # define TSI_OTAT_MRPFD (1<<18) |
---|
108 | # define TSI_OTAT_PFS(x) (((x)&3)<<16) |
---|
109 | # define TSI_OTAT_2eSSTM(x) (((x)&7)<<11) |
---|
110 | # define TSI_OTAT_2eSSTM_160 TSI_OTAT_2eSSTM(0) |
---|
111 | # define TSI_OTAT_2eSSTM_267 TSI_OTAT_2eSSTM(1) |
---|
112 | # define TSI_OTAT_2eSSTM_320 TSI_OTAT_2eSSTM(2) |
---|
113 | # define TSI_OTAT_TM(x) (((x)&7)<<8) |
---|
114 | # define TSI_TM_SCT_IDX 0 |
---|
115 | # define TSI_TM_BLT_IDX 1 |
---|
116 | # define TSI_TM_MBLT_IDX 2 |
---|
117 | # define TSI_TM_2eVME_IDX 3 |
---|
118 | # define TSI_TM_2eSST_IDX 4 |
---|
119 | # define TSI_TM_2eSSTB_IDX 5 |
---|
120 | # define TSI_OTAT_DBW(x) (((x)&3)<<6) |
---|
121 | # define TSI_OTAT_SUP (1<<5) |
---|
122 | # define TSI_OTAT_PGM (1<<4) |
---|
123 | # define TSI_OTAT_ADMODE(x) (((x)&0xf)) |
---|
124 | # define TSI_OTAT_ADMODE_A16 0 |
---|
125 | # define TSI_OTAT_ADMODE_A24 1 |
---|
126 | # define TSI_OTAT_ADMODE_A32 2 |
---|
127 | # define TSI_OTAT_ADMODE_A64 4 |
---|
128 | # define TSI_OTAT_ADMODE_CSR 5 |
---|
129 | # define TSI_OTAT_ADMODE_USR1 8 |
---|
130 | # define TSI_OTAT_ADMODE_USR2 9 |
---|
131 | # define TSI_OTAT_ADMODE_USR3 0xa |
---|
132 | # define TSI_OTAT_ADMODE_USR4 0xb |
---|
133 | |
---|
134 | #define TSI_VIACK_1_REG 0x204 |
---|
135 | |
---|
136 | #define TSI_VMCTRL_REG 0x234 |
---|
137 | # define TSI_VMCTRL_VSA (1<<27) |
---|
138 | # define TSI_VMCTRL_VS (1<<26) |
---|
139 | # define TSI_VMCTRL_DHB (1<<25) |
---|
140 | # define TSI_VMCTRL_DWB (1<<24) |
---|
141 | # define TSI_VMCTRL_RMWEN (1<<20) |
---|
142 | # define TSI_VMCTRL_A64DS (1<<16) |
---|
143 | # define TSI_VMCTRL_VTOFF_MSK (7<<12) |
---|
144 | # define TSI_VMCTRL_VTOFF_0us (0<<12) |
---|
145 | # define TSI_VMCTRL_VTOFF_1us (1<<12) |
---|
146 | # define TSI_VMCTRL_VTOFF_2us (2<<12) |
---|
147 | # define TSI_VMCTRL_VTOFF_4us (3<<12) |
---|
148 | # define TSI_VMCTRL_VTOFF_8us (4<<12) |
---|
149 | # define TSI_VMCTRL_VTOFF_16us (5<<12) |
---|
150 | # define TSI_VMCTRL_VTOFF_32us (6<<12) |
---|
151 | # define TSI_VMCTRL_VTOFF_64us (7<<12) |
---|
152 | # define TSI_VMCTRL_VTON_MSK (7<< 8) |
---|
153 | # define TSI_VMCTRL_VTON_4us (0<< 8) |
---|
154 | # define TSI_VMCTRL_VTON_8us (1<< 8) |
---|
155 | # define TSI_VMCTRL_VTON_16us (2<< 8) |
---|
156 | # define TSI_VMCTRL_VTON_32us (3<< 8) |
---|
157 | # define TSI_VMCTRL_VTON_64us (4<< 8) |
---|
158 | # define TSI_VMCTRL_VTON_128us (5<< 8) |
---|
159 | # define TSI_VMCTRL_VTON_256us (6<< 8) |
---|
160 | # define TSI_VMCTRL_VTON_512us (7<< 8) |
---|
161 | # define TSI_VMCTRL_VREL_MSK (3<< 3) |
---|
162 | # define TSI_VMCTRL_VREL_TON_or_DONE (0<< 3) |
---|
163 | # define TSI_VMCTRL_VREL_TONandREQ_or_DONE (1<< 3) |
---|
164 | # define TSI_VMCTRL_VREL_TONandBCLR_or_DONE (2<< 3) |
---|
165 | # define TSI_VMCTRL_VREL_TONorDONE_and_REQ (3<< 3) |
---|
166 | # define TSI_VMCTRL_VFAIR (1<< 2) |
---|
167 | # define TSI_VMCTRL_VREQL_MSK (3<< 0) |
---|
168 | # define TSI_VMCTRL_VREQL(x) ((x)&3) |
---|
169 | |
---|
170 | #define TSI_VCTRL_REG 0x238 |
---|
171 | #define TSI_VCTRL_DLT_MSK (0xf<<24) |
---|
172 | #define TSI_VCTRL_NELBB (1<<20) |
---|
173 | #define TSI_VCTRL_SRESET (1<<17) |
---|
174 | #define TSI_VCTRL_LRESET (1<<16) |
---|
175 | #define TSI_VCTRL_SFAILAI (1<<15) |
---|
176 | #define TSI_VCTRL_BID_MSK (0x1f<<8) |
---|
177 | #define TSI_VCTRL_ATOEN (1<< 7) |
---|
178 | #define TSI_VCTRL_ROBIN (1<< 6) |
---|
179 | #define TSI_VCTRL_GTO_MSK (7<< 0) |
---|
180 | |
---|
181 | |
---|
182 | #define TSI_VSTAT_REG 0x23c |
---|
183 | # define TSI_VSTAT_CPURST (1<<15) /* clear power-up reset bit */ |
---|
184 | # define TSI_VSTAT_BDFAIL (1<<14) |
---|
185 | # define TSI_VSTAT_PURSTS (1<<12) |
---|
186 | # define TSI_VSTAT_BDFAILS (1<<11) |
---|
187 | # define TSI_VSTAT_SYSFLS (1<<10) |
---|
188 | # define TSI_VSTAT_ACFAILS (1<< 9) |
---|
189 | # define TSI_VSTAT_SCONS (1<< 8) |
---|
190 | # define TSI_VSTAT_GAP (1<< 5) |
---|
191 | # define TSI_VSTAT_GA_MSK (0x1f) |
---|
192 | |
---|
193 | #define TSI_VEAU_REG 0x260 |
---|
194 | #define TSI_VEAL_REG 0x264 |
---|
195 | #define TSI_VEAT_REG 0x268 |
---|
196 | |
---|
197 | #define TSI_ITSAU_SPACING 0x020 |
---|
198 | |
---|
199 | #define TSI_ITSAU0_REG 0x300 |
---|
200 | #define TSI_ITSAL0_REG 0x304 |
---|
201 | #define TSI_ITEAU0_REG 0x308 |
---|
202 | #define TSI_ITEAL0_REG 0x30c |
---|
203 | #define TSI_ITOFU0_REG 0x310 |
---|
204 | #define TSI_ITOFL0_REG 0x314 |
---|
205 | #define TSI_ITAT0_REG 0x318 |
---|
206 | #define TSI_ITSAU_REG(port) (TSI_ITSAU0_REG + ((port)<<5)) |
---|
207 | #define TSI_ITSAL_REG(port) (TSI_ITSAL0_REG + ((port)<<5)) |
---|
208 | #define TSI_ITEAU_REG(port) (TSI_ITEAU0_REG + ((port)<<5)) |
---|
209 | #define TSI_ITEAL_REG(port) (TSI_ITEAL0_REG + ((port)<<5)) |
---|
210 | #define TSI_ITOFU_REG(port) (TSI_ITOFU0_REG + ((port)<<5)) |
---|
211 | #define TSI_ITOFL_REG(port) (TSI_ITOFL0_REG + ((port)<<5)) |
---|
212 | #define TSI_ITAT_REG(port) (TSI_ITAT0_REG + ((port)<<5)) |
---|
213 | |
---|
214 | # define TSI_ITAT_EN (1<<31) |
---|
215 | # define TSI_ITAT_TH (1<<18) |
---|
216 | # define TSI_ITAT_VFS(x) (((x)&3)<<16) |
---|
217 | # define TSI_ITAT_2eSSTM(x) (((x)&7)<<12) |
---|
218 | # define TSI_ITAT_2eSSTM_160 TSI_ITAT_2eSSTM(0) |
---|
219 | # define TSI_ITAT_2eSSTM_267 TSI_ITAT_2eSSTM(1) |
---|
220 | # define TSI_ITAT_2eSSTM_320 TSI_ITAT_2eSSTM(2) |
---|
221 | # define TSI_ITAT_2eSSTB (1<<11) |
---|
222 | # define TSI_ITAT_2eSST (1<<10) |
---|
223 | # define TSI_ITAT_2eVME (1<<9) |
---|
224 | # define TSI_ITAT_MBLT (1<<8) |
---|
225 | # define TSI_ITAT_BLT (1<<7) |
---|
226 | # define TSI_ITAT_AS(x) (((x)&7)<<4) |
---|
227 | # define TSI_ITAT_ADMODE_A16 (0<<4) |
---|
228 | # define TSI_ITAT_ADMODE_A24 (1<<4) |
---|
229 | # define TSI_ITAT_ADMODE_A32 (2<<4) |
---|
230 | # define TSI_ITAT_ADMODE_A64 (4<<4) |
---|
231 | # define TSI_ITAT_SUP (1<<3) |
---|
232 | # define TSI_ITAT_USR (1<<2) |
---|
233 | # define TSI_ITAT_PGM (1<<1) |
---|
234 | # define TSI_ITAT_DATA (1<<0) |
---|
235 | |
---|
236 | #define TSI_CBAU_REG 0x40c |
---|
237 | #define TSI_CBAL_REG 0x410 |
---|
238 | #define TSI_CRGAT_REG 0x414 |
---|
239 | # define TSI_CRGAT_EN (1<<7) |
---|
240 | # define TSI_CRGAT_AS_MSK (7<<4) |
---|
241 | # define TSI_CRGAT_A16 (0<<4) |
---|
242 | # define TSI_CRGAT_A24 (1<<4) |
---|
243 | # define TSI_CRGAT_A32 (2<<4) |
---|
244 | # define TSI_CRGAT_A64 (4<<4) |
---|
245 | # define TSI_CRGAT_SUP (1<<3) |
---|
246 | # define TSI_CRGAT_USR (1<<2) |
---|
247 | # define TSI_CRGAT_PGM (1<<1) |
---|
248 | # define TSI_CRGAT_DATA (1<<0) |
---|
249 | |
---|
250 | #define TSI_VICR_REG 0x440 |
---|
251 | # define TSI_VICR_CNTS(v) (((v)&3)<<30) |
---|
252 | # define TSI_VICR_CNTS_DIS (0<<30) |
---|
253 | # define TSI_VICR_CNTS_IRQ1 (1<<30) |
---|
254 | # define TSI_VICR_CNTS_IRQ2 (2<<30) |
---|
255 | # define TSI_VICR_EDGIS(v) (((v)&3)<<28) |
---|
256 | # define TSI_VICR_EDGIS_DIS (0<<28) |
---|
257 | # define TSI_VICR_EDGIS_IRQ1 (1<<28) |
---|
258 | # define TSI_VICR_EDGIS_IRQ2 (2<<28) |
---|
259 | # define TSI_VICR_IRQ1F(v) (((v)&3)<<26) |
---|
260 | # define TSI_VICR_IRQ1F_NORML (0<<26) |
---|
261 | # define TSI_VICR_IRQ1F_PULSE (1<<26) |
---|
262 | # define TSI_VICR_IRQ1F_CLOCK (2<<26) |
---|
263 | # define TSI_VICR_IRQ1F_1MHZ (3<<26) |
---|
264 | # define TSI_VICR_IRQ2F(v) (((v)&3)<<24) |
---|
265 | # define TSI_VICR_IRQ2F_NORML (0<<24) |
---|
266 | # define TSI_VICR_IRQ2F_PULSE (1<<24) |
---|
267 | # define TSI_VICR_IRQ2F_CLOCK (2<<24) |
---|
268 | # define TSI_VICR_IRQ2F_1MHZ (3<<24) |
---|
269 | # define TSI_VICR_BIP (1<<23) |
---|
270 | # define TSI_VICR_BIPS (1<<22) |
---|
271 | # define TSI_VICR_IRQC (1<<15) |
---|
272 | # define TSI_VICR_IRQLS(v) (((v)&7)<<12) |
---|
273 | # define TSI_VICR_IRQS (1<<11) |
---|
274 | # define TSI_VICR_IRQL(v) (((v)&7)<<8) |
---|
275 | # define TSI_VICR_STID(v) ((v)&0xff) |
---|
276 | #define TSI_INTEN_REG 0x448 |
---|
277 | #define TSI_INTEO_REG 0x44c |
---|
278 | #define TSI_INTS_REG 0x450 |
---|
279 | # define TSI_INTS_IRQ1S (1<<1) |
---|
280 | # define TSI_INTS_IRQ2S (1<<2) |
---|
281 | # define TSI_INTS_IRQ3S (1<<3) |
---|
282 | # define TSI_INTS_IRQ4S (1<<4) |
---|
283 | # define TSI_INTS_IRQ5S (1<<5) |
---|
284 | # define TSI_INTS_IRQ6S (1<<6) |
---|
285 | # define TSI_INTS_IRQ7S (1<<7) |
---|
286 | # define TSI_INTS_ACFLS (1<<8) |
---|
287 | # define TSI_INTS_SYSFLS (1<<9) |
---|
288 | # define TSI_INTS_IACKS (1<<10) |
---|
289 | # define TSI_INTS_VIES (1<<11) |
---|
290 | # define TSI_INTS_VERRS (1<<12) |
---|
291 | # define TSI_INTS_PERRS (1<<13) |
---|
292 | # define TSI_INTS_MB0S (1<<16) |
---|
293 | # define TSI_INTS_MB1S (1<<17) |
---|
294 | # define TSI_INTS_MB2S (1<<18) |
---|
295 | # define TSI_INTS_MB3S (1<<19) |
---|
296 | # define TSI_INTS_LM0S (1<<20) |
---|
297 | # define TSI_INTS_LM1S (1<<21) |
---|
298 | # define TSI_INTS_LM2S (1<<22) |
---|
299 | # define TSI_INTS_LM3S (1<<23) |
---|
300 | # define TSI_INTS_DMA0S (1<<24) |
---|
301 | # define TSI_INTS_DMA1S (1<<25) |
---|
302 | #define TSI_INTC_REG 0x454 |
---|
303 | # define TSI_INTC_ACFLC (1<<8) |
---|
304 | # define TSI_INTC_SYSFLC (1<<9) |
---|
305 | # define TSI_INTC_IACKC (1<<10) |
---|
306 | # define TSI_INTC_VIEC (1<<11) |
---|
307 | # define TSI_INTC_VERRC (1<<12) |
---|
308 | # define TSI_INTC_PERRC (1<<13) |
---|
309 | # define TSI_INTC_MB0C (1<<16) |
---|
310 | # define TSI_INTC_MB1C (1<<17) |
---|
311 | # define TSI_INTC_MB2C (1<<18) |
---|
312 | # define TSI_INTC_MB3C (1<<19) |
---|
313 | # define TSI_INTC_LM0C (1<<20) |
---|
314 | # define TSI_INTC_LM1C (1<<21) |
---|
315 | # define TSI_INTC_LM2C (1<<22) |
---|
316 | # define TSI_INTC_LM3C (1<<23) |
---|
317 | # define TSI_INTC_DMA0C (1<<24) |
---|
318 | # define TSI_INTC_DMA1C (1<<25) |
---|
319 | #define TSI_INTM1_REG 0x458 |
---|
320 | #define TSI_INTM2_REG 0x45c |
---|
321 | |
---|
322 | #define TSI_CBAR_REG 0xffc |
---|
323 | |
---|
324 | #define TSI_CSR_OFFSET 0x7f000 |
---|
325 | |
---|
326 | #define TSI_CRG_SIZE (1<<12) /* 4k */ |
---|
327 | |
---|
328 | |
---|
329 | #define TSI_RD(base, reg) in_be32((volatile uint32_t *)((base) + (reg)/sizeof(*base))) |
---|
330 | #define TSI_RD16(base, reg) in_be16((volatile uint16_t *)(base) + (reg)/sizeof(uint16_t)) |
---|
331 | #define TSI_LE_RD16(base, reg) in_le16((volatile uint16_t *)(base) + (reg)/sizeof(uint16_t)) |
---|
332 | #define TSI_LE_RD32(base, reg) in_le32((volatile uint32_t *)(base) + (reg)/sizeof(*base)) |
---|
333 | #define TSI_RD8(base, reg) in_8((volatile uint8_t *)(base) + (reg)) |
---|
334 | #define TSI_WR(base, reg, val) out_be32((volatile uint32_t *)((base) + (reg)/sizeof(*base)), val) |
---|
335 | |
---|
336 | #define UNIV_SCTL_AM_MASK (UNIV_CTL_VAS | UNIV_SCTL_PGM | UNIV_SCTL_DAT | UNIV_SCTL_USER | UNIV_SCTL_SUPER) |
---|
337 | |
---|
338 | |
---|
339 | /* allow the BSP to override the default routines */ |
---|
340 | #ifndef BSP_PCI_FIND_DEVICE |
---|
341 | #define BSP_PCI_FIND_DEVICE pci_find_device |
---|
342 | #endif |
---|
343 | #ifndef BSP_PCI_CONFIG_IN_LONG |
---|
344 | #define BSP_PCI_CONFIG_IN_LONG pci_read_config_dword |
---|
345 | #endif |
---|
346 | #ifndef BSP_PCI_CONFIG_IN_SHORT |
---|
347 | #define BSP_PCI_CONFIG_IN_SHORT pci_read_config_word |
---|
348 | #endif |
---|
349 | #ifndef BSP_PCI_CONFIG_OUT_SHORT |
---|
350 | #define BSP_PCI_CONFIG_OUT_SHORT pci_write_config_word |
---|
351 | #endif |
---|
352 | #ifndef BSP_PCI_CONFIG_IN_BYTE |
---|
353 | #define BSP_PCI_CONFIG_IN_BYTE pci_read_config_byte |
---|
354 | #endif |
---|
355 | |
---|
356 | typedef uint32_t pci_ulong; |
---|
357 | |
---|
358 | #ifdef __BIG_ENDIAN__ |
---|
359 | static inline void st_be32( uint32_t *a, uint32_t v) |
---|
360 | { |
---|
361 | *a = v; |
---|
362 | } |
---|
363 | static inline uint32_t ld_be32( uint32_t *a ) |
---|
364 | { |
---|
365 | return *a; |
---|
366 | } |
---|
367 | #elif defined(__LITTLE_ENDIAN__) |
---|
368 | #error "You need to implement st_be32/ld_be32" |
---|
369 | #else |
---|
370 | #error "Undefined endianness??" |
---|
371 | #endif |
---|
372 | |
---|
373 | #ifndef BSP_LOCAL2PCI_ADDR |
---|
374 | /* try legacy PCI_DRAM_OFFSET */ |
---|
375 | #ifndef PCI_DRAM_OFFSET |
---|
376 | #define PCI_DRAM_OFFSET 0 |
---|
377 | #endif |
---|
378 | #define BSP_LOCAL2PCI_ADDR(l) (((uint32_t)l)+PCI_DRAM_OFFSET) |
---|
379 | #endif |
---|
380 | |
---|
381 | /* PCI_MEM_BASE is a possible offset between CPU- and PCI addresses. |
---|
382 | * Should be defined by the BSP. |
---|
383 | */ |
---|
384 | #ifndef BSP_PCI2LOCAL_ADDR |
---|
385 | #ifndef PCI_MEM_BASE |
---|
386 | #define PCI_MEM_BASE 0 |
---|
387 | #endif |
---|
388 | #define BSP_PCI2LOCAL_ADDR(memaddr) ((unsigned long)(memaddr) + PCI_MEM_BASE) |
---|
389 | #endif |
---|
390 | |
---|
391 | typedef uint32_t BEValue; |
---|
392 | |
---|
393 | typedef struct { |
---|
394 | BERegister *base; |
---|
395 | int irqLine; |
---|
396 | int pic_pin[TSI_NUM_WIRES]; |
---|
397 | } Tsi148Dev; |
---|
398 | |
---|
399 | static Tsi148Dev devs[NUM_TSI_DEVS] = {{0}}; |
---|
400 | |
---|
401 | #define THEBASE (devs[0].base) |
---|
402 | |
---|
403 | /* forward decl */ |
---|
404 | extern int vmeTsi148RegPort; |
---|
405 | extern int vmeTsi148RegCSR; |
---|
406 | |
---|
407 | /* registers should be mapped to guarded, non-cached memory; hence |
---|
408 | * subsequent stores are ordered. eieio is only needed to enforce |
---|
409 | * ordering of loads with respect to stores. |
---|
410 | */ |
---|
411 | |
---|
412 | /* private printing wrapper */ |
---|
413 | static void |
---|
414 | uprintf(FILE *f, char *fmt, ...) |
---|
415 | { |
---|
416 | va_list ap; |
---|
417 | va_start(ap, fmt); |
---|
418 | if (!f || !_impure_ptr->__sdidinit) { |
---|
419 | /* Might be called at an early stage when |
---|
420 | * to a buffer. |
---|
421 | */ |
---|
422 | vprintk(fmt,ap); |
---|
423 | } else |
---|
424 | { |
---|
425 | vfprintf(f,fmt,ap); |
---|
426 | } |
---|
427 | va_end(ap); |
---|
428 | } |
---|
429 | |
---|
430 | #define CHECK_BASE(base,quiet,rval) \ |
---|
431 | do { \ |
---|
432 | if ( !base ) { \ |
---|
433 | if ( !quiet ) { \ |
---|
434 | uprintf(stderr,"Tsi148: Driver not initialized\n"); \ |
---|
435 | } \ |
---|
436 | return rval; \ |
---|
437 | } \ |
---|
438 | } while (0) |
---|
439 | |
---|
440 | int |
---|
441 | vmeTsi148FindPciBase( |
---|
442 | int instance, |
---|
443 | BERegister **pbase |
---|
444 | ) |
---|
445 | { |
---|
446 | int bus,dev,fun; |
---|
447 | pci_ulong busaddr; |
---|
448 | unsigned char irqline; |
---|
449 | unsigned short wrd; |
---|
450 | |
---|
451 | if (BSP_PCI_FIND_DEVICE( |
---|
452 | PCI_VENDOR_TUNDRA, |
---|
453 | PCI_DEVICE_TSI148, |
---|
454 | instance, |
---|
455 | &bus, |
---|
456 | &dev, |
---|
457 | &fun)) |
---|
458 | return -1; |
---|
459 | if (BSP_PCI_CONFIG_IN_LONG(bus,dev,fun,PCI_BASE_ADDRESS_0,&busaddr)) |
---|
460 | return -1; |
---|
461 | /* Assume upper BAR is zero */ |
---|
462 | |
---|
463 | *pbase=(BERegister*)(((pci_ulong)BSP_PCI2LOCAL_ADDR(busaddr)) & ~0xff); |
---|
464 | |
---|
465 | if (BSP_PCI_CONFIG_IN_BYTE(bus,dev,fun,PCI_INTERRUPT_LINE,&irqline)) |
---|
466 | return -1; |
---|
467 | |
---|
468 | /* Enable PCI master and memory access */ |
---|
469 | BSP_PCI_CONFIG_IN_SHORT(bus, dev, fun, PCI_COMMAND, &wrd); |
---|
470 | BSP_PCI_CONFIG_OUT_SHORT(bus, dev, fun, PCI_COMMAND, wrd | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); |
---|
471 | |
---|
472 | return irqline; |
---|
473 | } |
---|
474 | |
---|
475 | int |
---|
476 | vmeTsi148InitInstance(unsigned instance) |
---|
477 | { |
---|
478 | int irq; |
---|
479 | BERegister *base; |
---|
480 | |
---|
481 | if ( instance >= NUM_TSI_DEVS ) |
---|
482 | return -1; |
---|
483 | if ( devs[instance].base ) |
---|
484 | return -1; |
---|
485 | |
---|
486 | if ((irq=vmeTsi148FindPciBase(instance,&base)) < 0) { |
---|
487 | uprintf(stderr,"unable to find a Tsi148 in pci config space\n"); |
---|
488 | } else { |
---|
489 | uprintf(stderr,"Tundra Tsi148 PCI-VME bridge detected at 0x%08x, IRQ %d\n", |
---|
490 | (unsigned int)base, irq); |
---|
491 | } |
---|
492 | devs[0].base = base; |
---|
493 | devs[0].irqLine = irq; |
---|
494 | |
---|
495 | return irq < 0 ? -1 : 0; |
---|
496 | } |
---|
497 | |
---|
498 | int |
---|
499 | vmeTsi148Init(void) |
---|
500 | { |
---|
501 | return vmeTsi148InitInstance(0); |
---|
502 | } |
---|
503 | |
---|
504 | |
---|
505 | void |
---|
506 | vmeTsi148ResetXX(BERegister *base) |
---|
507 | { |
---|
508 | int port; |
---|
509 | uint32_t v; |
---|
510 | |
---|
511 | CHECK_BASE(base,0, ); |
---|
512 | |
---|
513 | vmeTsi148DisableAllOutboundPortsXX(base); |
---|
514 | for ( port=0; port < TSI148_NUM_OPORTS; port++ ) |
---|
515 | TSI_WR(base, TSI_OTBS_REG(port), 0); |
---|
516 | TSI_WR(base, TSI_INTEO_REG, 0); |
---|
517 | TSI_WR(base, TSI_INTEN_REG, 0); |
---|
518 | TSI_WR(base, TSI_INTC_REG, 0xffffffff); |
---|
519 | TSI_WR(base, TSI_INTM1_REG, 0); |
---|
520 | TSI_WR(base, TSI_INTM2_REG, 0); |
---|
521 | TSI_WR(base, TSI_VICR_REG, 0); |
---|
522 | TSI_WR(base, TSI_VEAT_REG, TSI_VEAT_VESCL); |
---|
523 | /* Clear BDFAIL / (--> SYSFAIL) */ |
---|
524 | # define TSI_VSTAT_BDFAIL (1<<14) |
---|
525 | TSI_WR(base, TSI_VSTAT_REG, TSI_RD(base, TSI_VSTAT_REG) & ~TSI_VSTAT_BDFAIL); |
---|
526 | /* Set (long) bus master timeout; the timeout actually overrides |
---|
527 | * the DMA block size so that the DMA settings would effectively |
---|
528 | * not be used. |
---|
529 | * Also, we enable 'release on request' mode so that we normally |
---|
530 | * don't have to rearbitrate the bus for every transfer. |
---|
531 | */ |
---|
532 | v = TSI_RD(base, TSI_VMCTRL_REG); |
---|
533 | v &= ~( TSI_VMCTRL_VTON_MSK | TSI_VMCTRL_VREL_MSK ); |
---|
534 | v |= (TSI_VMCTRL_VTON_512us | TSI_VMCTRL_VREL_TONorDONE_and_REQ ); |
---|
535 | TSI_WR(base, TSI_VMCTRL_REG, v); |
---|
536 | } |
---|
537 | |
---|
538 | void |
---|
539 | vmeTsi148Reset(void) |
---|
540 | { |
---|
541 | vmeTsi148ResetXX(THEBASE); |
---|
542 | } |
---|
543 | |
---|
544 | void |
---|
545 | vmeTsi148ResetBusXX(BERegister *base) |
---|
546 | { |
---|
547 | unsigned long flags; |
---|
548 | uint32_t v; |
---|
549 | |
---|
550 | rtems_interrupt_disable(flags); |
---|
551 | v = TSI_RD(base, TSI_VCTRL_REG); |
---|
552 | TSI_WR(base, TSI_VCTRL_REG, v | TSI_VCTRL_SRESET); |
---|
553 | rtems_interrupt_enable(flags); |
---|
554 | } |
---|
555 | |
---|
556 | void |
---|
557 | vmeTsi148ResetBus(void) |
---|
558 | { |
---|
559 | vmeTsi148ResetBusXX(THEBASE); |
---|
560 | } |
---|
561 | |
---|
562 | |
---|
563 | /* convert an address space selector to a corresponding |
---|
564 | * Tsi148 control mode word |
---|
565 | */ |
---|
566 | |
---|
567 | static unsigned long ck2esst(unsigned long am) |
---|
568 | { |
---|
569 | if ( VME_AM_IS_2eSST(am) ) { |
---|
570 | /* make sure 2eVME is selected */ |
---|
571 | am &= ~VME_AM_MASK; |
---|
572 | am |= VME_AM_2eVME_6U; |
---|
573 | } |
---|
574 | return am; |
---|
575 | } |
---|
576 | |
---|
577 | static int |
---|
578 | am2omode(unsigned long address_space, unsigned long *pmode) |
---|
579 | { |
---|
580 | unsigned long mode = 0; |
---|
581 | unsigned long tm = TSI_TM_SCT_IDX; |
---|
582 | |
---|
583 | switch ( VME_MODE_DBW_MSK & address_space ) { |
---|
584 | case VME_MODE_DBW8: |
---|
585 | return -1; /* unsupported */ |
---|
586 | |
---|
587 | case VME_MODE_DBW16: |
---|
588 | break; |
---|
589 | |
---|
590 | default: |
---|
591 | case VME_MODE_DBW32: |
---|
592 | mode |= TSI_OTAT_DBW(1); |
---|
593 | break; |
---|
594 | } |
---|
595 | |
---|
596 | if ( ! (VME_MODE_PREFETCH_ENABLE & address_space) ) |
---|
597 | mode |= TSI_OTAT_MRPFD; |
---|
598 | else { |
---|
599 | mode |= TSI_OTAT_PFS(address_space>>_LD_VME_MODE_PREFETCHSZ); |
---|
600 | } |
---|
601 | |
---|
602 | address_space = ck2esst(address_space); |
---|
603 | |
---|
604 | switch (address_space & VME_AM_MASK) { |
---|
605 | case VME_AM_STD_SUP_PGM: |
---|
606 | case VME_AM_STD_USR_PGM: |
---|
607 | |
---|
608 | mode |= TSI_OTAT_PGM; |
---|
609 | |
---|
610 | /* fall thru */ |
---|
611 | case VME_AM_STD_SUP_BLT: |
---|
612 | case VME_AM_STD_SUP_MBLT: |
---|
613 | |
---|
614 | case VME_AM_STD_USR_BLT: |
---|
615 | case VME_AM_STD_USR_MBLT: |
---|
616 | switch ( address_space & 3 ) { |
---|
617 | case 0: tm = TSI_TM_MBLT_IDX; break; |
---|
618 | case 3: tm = TSI_TM_BLT_IDX; break; |
---|
619 | default: break; |
---|
620 | } |
---|
621 | |
---|
622 | case VME_AM_STD_SUP_DATA: |
---|
623 | case VME_AM_STD_USR_DATA: |
---|
624 | |
---|
625 | mode |= TSI_OTAT_ADMODE_A24; |
---|
626 | break; |
---|
627 | |
---|
628 | case VME_AM_EXT_SUP_PGM: |
---|
629 | case VME_AM_EXT_USR_PGM: |
---|
630 | mode |= TSI_OTAT_PGM; |
---|
631 | |
---|
632 | /* fall thru */ |
---|
633 | case VME_AM_EXT_SUP_BLT: |
---|
634 | case VME_AM_EXT_SUP_MBLT: |
---|
635 | |
---|
636 | case VME_AM_EXT_USR_BLT: |
---|
637 | case VME_AM_EXT_USR_MBLT: |
---|
638 | switch ( address_space & 3 ) { |
---|
639 | case 0: tm = TSI_TM_MBLT_IDX; break; |
---|
640 | case 3: tm = TSI_TM_BLT_IDX; break; |
---|
641 | default: break; |
---|
642 | } |
---|
643 | |
---|
644 | case VME_AM_EXT_SUP_DATA: |
---|
645 | case VME_AM_EXT_USR_DATA: |
---|
646 | |
---|
647 | mode |= TSI_OTAT_ADMODE_A32; |
---|
648 | break; |
---|
649 | |
---|
650 | case VME_AM_SUP_SHORT_IO: |
---|
651 | case VME_AM_USR_SHORT_IO: |
---|
652 | mode |= TSI_OTAT_ADMODE_A16; |
---|
653 | break; |
---|
654 | |
---|
655 | case VME_AM_CSR: |
---|
656 | mode |= TSI_OTAT_ADMODE_CSR; |
---|
657 | break; |
---|
658 | |
---|
659 | case VME_AM_2eVME_6U: |
---|
660 | case VME_AM_2eVME_3U: |
---|
661 | mode |= TSI_OTAT_ADMODE_A32; |
---|
662 | if ( VME_AM_IS_2eSST(address_space) ) { |
---|
663 | tm = ( VME_AM_2eSST_BCST & address_space ) ? |
---|
664 | TSI_TM_2eSSTB_IDX : TSI_TM_2eSST_IDX; |
---|
665 | switch ( VME_AM_IS_2eSST(address_space) ) { |
---|
666 | default: |
---|
667 | case VME_AM_2eSST_LO: mode |= TSI_OTAT_2eSSTM_160; break; |
---|
668 | case VME_AM_2eSST_MID: mode |= TSI_OTAT_2eSSTM_267; break; |
---|
669 | case VME_AM_2eSST_HI: mode |= TSI_OTAT_2eSSTM_320; break; |
---|
670 | } |
---|
671 | } else { |
---|
672 | tm = TSI_TM_2eVME_IDX; |
---|
673 | } |
---|
674 | break; |
---|
675 | |
---|
676 | case 0: /* disable the port alltogether */ |
---|
677 | break; |
---|
678 | |
---|
679 | default: |
---|
680 | return -1; |
---|
681 | } |
---|
682 | |
---|
683 | mode |= TSI_OTAT_TM(tm); |
---|
684 | |
---|
685 | if ( VME_AM_IS_SUP(address_space) ) |
---|
686 | mode |= TSI_OTAT_SUP; |
---|
687 | *pmode = mode; |
---|
688 | return 0; |
---|
689 | } |
---|
690 | |
---|
691 | static int |
---|
692 | am2imode(unsigned long address_space, unsigned long *pmode) |
---|
693 | { |
---|
694 | unsigned long mode=0; |
---|
695 | unsigned long pgm = 0; |
---|
696 | |
---|
697 | mode |= TSI_ITAT_VFS(address_space>>_LD_VME_MODE_PREFETCHSZ); |
---|
698 | |
---|
699 | if ( VME_AM_IS_2eSST(address_space) ) { |
---|
700 | mode |= TSI_ITAT_2eSST; |
---|
701 | if ( VME_AM_2eSST_BCST & address_space ) |
---|
702 | mode |= TSI_ITAT_2eSSTB; |
---|
703 | switch ( VME_AM_IS_2eSST(address_space) ) { |
---|
704 | default: |
---|
705 | case VME_AM_2eSST_LO: mode |= TSI_ITAT_2eSSTM_160; break; |
---|
706 | case VME_AM_2eSST_MID: mode |= TSI_ITAT_2eSSTM_267; break; |
---|
707 | case VME_AM_2eSST_HI: mode |= TSI_ITAT_2eSSTM_320; break; |
---|
708 | } |
---|
709 | address_space = ck2esst(address_space); |
---|
710 | } |
---|
711 | |
---|
712 | mode |= TSI_ITAT_BLT; |
---|
713 | mode |= TSI_ITAT_MBLT; |
---|
714 | |
---|
715 | mode |= TSI_ITAT_PGM; /* always allow PGM access */ |
---|
716 | mode |= TSI_ITAT_USR; /* always allow USR access */ |
---|
717 | |
---|
718 | switch (address_space & VME_AM_MASK) { |
---|
719 | case VME_AM_STD_SUP_PGM: |
---|
720 | case VME_AM_STD_USR_PGM: |
---|
721 | |
---|
722 | pgm = 1; |
---|
723 | |
---|
724 | /* fall thru */ |
---|
725 | case VME_AM_STD_SUP_BLT: |
---|
726 | case VME_AM_STD_SUP_MBLT: |
---|
727 | case VME_AM_STD_USR_BLT: |
---|
728 | case VME_AM_STD_USR_MBLT: |
---|
729 | case VME_AM_STD_SUP_DATA: |
---|
730 | case VME_AM_STD_USR_DATA: |
---|
731 | |
---|
732 | mode |= TSI_ITAT_ADMODE_A24; |
---|
733 | break; |
---|
734 | |
---|
735 | case VME_AM_EXT_SUP_PGM: |
---|
736 | case VME_AM_EXT_USR_PGM: |
---|
737 | pgm = 1; |
---|
738 | |
---|
739 | /* fall thru */ |
---|
740 | case VME_AM_2eVME_6U: |
---|
741 | case VME_AM_2eVME_3U: |
---|
742 | case VME_AM_EXT_SUP_BLT: |
---|
743 | case VME_AM_EXT_SUP_MBLT: |
---|
744 | case VME_AM_EXT_USR_BLT: |
---|
745 | case VME_AM_EXT_USR_MBLT: |
---|
746 | case VME_AM_EXT_SUP_DATA: |
---|
747 | case VME_AM_EXT_USR_DATA: |
---|
748 | mode |= TSI_ITAT_ADMODE_A32; |
---|
749 | break; |
---|
750 | |
---|
751 | case VME_AM_SUP_SHORT_IO: |
---|
752 | case VME_AM_USR_SHORT_IO: |
---|
753 | mode |= TSI_ITAT_ADMODE_A16; |
---|
754 | break; |
---|
755 | |
---|
756 | case 0: /* disable the port alltogether */ |
---|
757 | *pmode = 0; |
---|
758 | return 0; |
---|
759 | |
---|
760 | default: |
---|
761 | return -1; |
---|
762 | } |
---|
763 | |
---|
764 | if ( VME_AM_IS_SUP(address_space) ) |
---|
765 | mode |= TSI_ITAT_SUP; |
---|
766 | |
---|
767 | if ( !pgm ) |
---|
768 | mode |= TSI_ITAT_DATA; |
---|
769 | |
---|
770 | *pmode = mode; |
---|
771 | return 0; |
---|
772 | } |
---|
773 | |
---|
774 | static void |
---|
775 | readTriple( |
---|
776 | BERegister *base, |
---|
777 | unsigned reg, |
---|
778 | unsigned long long *ps, |
---|
779 | unsigned long long *pl, |
---|
780 | unsigned long long *po) |
---|
781 | { |
---|
782 | *ps = TSI_RD(base, reg); |
---|
783 | *ps = (*ps<<32) | (TSI_RD(base, (reg+4)) & 0xffff0000); |
---|
784 | *pl = TSI_RD(base, (reg+8)); |
---|
785 | *pl = (*pl<<32) | (TSI_RD(base, (reg+0xc)) & 0xffff0000); |
---|
786 | *po = TSI_RD(base, (reg+0x10)); |
---|
787 | *po = (*po<<32) | (TSI_RD(base, (reg+0x14)) & 0xffff0000); |
---|
788 | } |
---|
789 | |
---|
790 | |
---|
791 | static unsigned long |
---|
792 | inboundGranularity(unsigned long itat) |
---|
793 | { |
---|
794 | switch ( itat & TSI_ITAT_AS(-1) ) { |
---|
795 | case TSI_ITAT_ADMODE_A16: return 0xf; |
---|
796 | case TSI_ITAT_ADMODE_A24: return 0xfff; |
---|
797 | default: |
---|
798 | break; |
---|
799 | } |
---|
800 | return 0xffff; |
---|
801 | } |
---|
802 | |
---|
803 | static int |
---|
804 | configTsiPort( |
---|
805 | BERegister *base, |
---|
806 | int isout, |
---|
807 | unsigned long port, |
---|
808 | unsigned long address_space, |
---|
809 | unsigned long vme_address, |
---|
810 | unsigned long pci_address, |
---|
811 | unsigned long length) |
---|
812 | { |
---|
813 | unsigned long long start, limit, offst; |
---|
814 | unsigned long mode, mask, tat_reg, tsau_reg; |
---|
815 | char *name = (isout ? "Outbound" : "Inbound"); |
---|
816 | int i,s,l; |
---|
817 | |
---|
818 | CHECK_BASE(base,0,-1); |
---|
819 | |
---|
820 | mode = 0; /* silence warning */ |
---|
821 | |
---|
822 | if ( port >= (isout ? TSI148_NUM_OPORTS : TSI148_NUM_IPORTS) ) { |
---|
823 | uprintf(stderr,"Tsi148 %s Port Cfg: invalid port\n", name); |
---|
824 | return -1; |
---|
825 | } |
---|
826 | |
---|
827 | if ( base == THEBASE && isout && vmeTsi148RegPort == port ) { |
---|
828 | uprintf(stderr,"Tsi148 %s Port Cfg: invalid port; reserved by the interrupt manager for CRG\n", name); |
---|
829 | return -1; |
---|
830 | } |
---|
831 | |
---|
832 | if ( length && (isout ? am2omode(address_space, &mode) : am2imode(address_space, &mode)) ) { |
---|
833 | uprintf(stderr,"Tsi148 %s Port Cfg: invalid address space / mode flags\n",name); |
---|
834 | return -1; |
---|
835 | } |
---|
836 | |
---|
837 | |
---|
838 | if ( isout ) { |
---|
839 | start = pci_address; |
---|
840 | offst = (unsigned long long)vme_address - start; |
---|
841 | mask = 0xffff; |
---|
842 | tat_reg = TSI_OTAT_REG(port); |
---|
843 | tsau_reg = TSI_OTSAU_REG(port); |
---|
844 | mode |= TSI_OTAT_EN; |
---|
845 | |
---|
846 | /* check for overlap */ |
---|
847 | for ( i = 0; i < TSI148_NUM_OPORTS; i++ ) { |
---|
848 | /* ignore 'this' port */ |
---|
849 | if ( i == port || ! (TSI_OTAT_EN & TSI_RD(base, TSI_OTAT_REG(i))) ) |
---|
850 | continue; |
---|
851 | |
---|
852 | /* check requested PCI range against current port 'i' config */ |
---|
853 | s = TSI_RD(base, TSI_OTSAU_REG(i) + 0x04); /* start */ |
---|
854 | l = TSI_RD(base, TSI_OTSAU_REG(i) + 0x0c); /* limit */ |
---|
855 | if ( ! ( start + length <= s || start > s + l ) ) { |
---|
856 | uprintf(stderr,"Tsi148 Outbound Port Cfg: PCI address range overlaps with port %i (0x%08x..0x%08x)\n", i, s, l); |
---|
857 | return -1; |
---|
858 | } |
---|
859 | } |
---|
860 | } else { |
---|
861 | start = vme_address; |
---|
862 | offst = (unsigned long long)pci_address - start; |
---|
863 | mask = inboundGranularity(mode); |
---|
864 | tat_reg = TSI_ITAT_REG(port); |
---|
865 | tsau_reg = TSI_ITSAU_REG(port); |
---|
866 | mode |= TSI_ITAT_EN; |
---|
867 | |
---|
868 | /* check for overlap */ |
---|
869 | for ( i = 0; i < TSI148_NUM_IPORTS; i++ ) { |
---|
870 | /* ignore 'this' port */ |
---|
871 | if ( i == port || ! (TSI_ITAT_EN & (s=TSI_RD(base, TSI_ITAT_REG(i)))) ) |
---|
872 | continue; |
---|
873 | |
---|
874 | if ( (TSI_ITAT_AS(-1) & s) != (TSI_ITAT_AS(-1) & mode) ) { |
---|
875 | /* different address space */ |
---|
876 | continue; |
---|
877 | } |
---|
878 | |
---|
879 | if ( ! (mode & s & (TSI_ITAT_SUP | TSI_ITAT_USR | TSI_ITAT_PGM | TSI_ITAT_DATA)) ) { |
---|
880 | /* orthogonal privileges */ |
---|
881 | continue; |
---|
882 | } |
---|
883 | |
---|
884 | /* check requested VME range against current port 'i' config */ |
---|
885 | s = TSI_RD(base, TSI_ITSAU_REG(i) + 0x04); /* start */ |
---|
886 | l = TSI_RD(base, TSI_ITSAU_REG(i) + 0x0c); /* limit */ |
---|
887 | if ( ! ( start + length <= s || start > s + l ) ) { |
---|
888 | uprintf(stderr,"Tsi148 Inbound Port Cfg: VME address range overlaps with port %i (0x%08x..0x%08x)\n", i, s, l); |
---|
889 | return -1; |
---|
890 | } |
---|
891 | } |
---|
892 | } |
---|
893 | |
---|
894 | /* If they pass 'length==0' just disable */ |
---|
895 | if ( 0 == length ) { |
---|
896 | TSI_WR(base, tat_reg, TSI_RD(base, tat_reg) & ~(isout ? TSI_OTAT_EN : TSI_ITAT_EN)); |
---|
897 | return 0; |
---|
898 | } |
---|
899 | |
---|
900 | |
---|
901 | if ( (vme_address & mask) |
---|
902 | || (pci_address & mask) |
---|
903 | || (length & mask) ) { |
---|
904 | uprintf(stderr,"Tsi148 %s Port Cfg: invalid address/length; must be multiple of 0x%x\n", |
---|
905 | name, |
---|
906 | mask+1); |
---|
907 | return -1; |
---|
908 | } |
---|
909 | |
---|
910 | limit = start + length - 1; |
---|
911 | |
---|
912 | if ( limit >= (unsigned long long)1<<32 ) { |
---|
913 | uprintf(stderr,"Tsi148 %s Port Cfg: invalid address/length; must be < 1<<32\n", name); |
---|
914 | return -1; |
---|
915 | } |
---|
916 | |
---|
917 | /* Disable port */ |
---|
918 | TSI_WR(base, tat_reg, 0); |
---|
919 | |
---|
920 | /* Force to 32-bits */ |
---|
921 | TSI_WR(base, tsau_reg , 0); |
---|
922 | TSI_WR(base, tsau_reg + 0x04, (uint32_t)start); |
---|
923 | TSI_WR(base, tsau_reg + 0x08, 0); |
---|
924 | TSI_WR(base, tsau_reg + 0x0c, (uint32_t)limit); |
---|
925 | TSI_WR(base, tsau_reg + 0x10, (uint32_t)(offst>>32)); |
---|
926 | TSI_WR(base, tsau_reg + 0x14, (uint32_t)offst); |
---|
927 | |
---|
928 | /* (outbound only:) leave 2eSST broadcast register alone for user to program */ |
---|
929 | |
---|
930 | /* Set mode and enable */ |
---|
931 | TSI_WR(base, tat_reg, mode); |
---|
932 | return 0; |
---|
933 | } |
---|
934 | |
---|
935 | static int |
---|
936 | disableTsiPort( |
---|
937 | BERegister *base, |
---|
938 | int isout, |
---|
939 | unsigned long port) |
---|
940 | { |
---|
941 | return configTsiPort(base, isout, port, 0, 0, 0, 0); |
---|
942 | } |
---|
943 | |
---|
944 | int |
---|
945 | vmeTsi148InboundPortCfgXX( |
---|
946 | BERegister *base, |
---|
947 | unsigned long port, |
---|
948 | unsigned long address_space, |
---|
949 | unsigned long vme_address, |
---|
950 | unsigned long pci_address, |
---|
951 | unsigned long length) |
---|
952 | { |
---|
953 | return configTsiPort(base, 0, port, address_space, vme_address, pci_address, length); |
---|
954 | } |
---|
955 | |
---|
956 | int |
---|
957 | vmeTsi148InboundPortCfg( |
---|
958 | unsigned long port, |
---|
959 | unsigned long address_space, |
---|
960 | unsigned long vme_address, |
---|
961 | unsigned long pci_address, |
---|
962 | unsigned long length) |
---|
963 | { |
---|
964 | return configTsiPort(THEBASE, 0, port, address_space, vme_address, pci_address, length); |
---|
965 | } |
---|
966 | |
---|
967 | |
---|
968 | int |
---|
969 | vmeTsi148OutboundPortCfgXX( |
---|
970 | BERegister *base, |
---|
971 | unsigned long port, |
---|
972 | unsigned long address_space, |
---|
973 | unsigned long vme_address, |
---|
974 | unsigned long pci_address, |
---|
975 | unsigned long length) |
---|
976 | { |
---|
977 | return configTsiPort(base, 1, port, address_space, vme_address, pci_address, length); |
---|
978 | } |
---|
979 | |
---|
980 | int |
---|
981 | vmeTsi148OutboundPortCfg( |
---|
982 | unsigned long port, |
---|
983 | unsigned long address_space, |
---|
984 | unsigned long vme_address, |
---|
985 | unsigned long pci_address, |
---|
986 | unsigned long length) |
---|
987 | { |
---|
988 | return configTsiPort(THEBASE, 1, port, address_space, vme_address, pci_address, length); |
---|
989 | } |
---|
990 | |
---|
991 | |
---|
992 | static int |
---|
993 | xlateFindPort( |
---|
994 | BERegister *base, /* TSI 148 base address */ |
---|
995 | int outbound, /* look in the outbound windows */ |
---|
996 | int reverse, /* reverse mapping; for outbound ports: map local to VME */ |
---|
997 | unsigned long as, /* address space */ |
---|
998 | unsigned long aIn, /* address to look up */ |
---|
999 | unsigned long *paOut/* where to put result */ |
---|
1000 | ) |
---|
1001 | { |
---|
1002 | unsigned long mode, mode_msk; |
---|
1003 | int port; |
---|
1004 | unsigned long long start, limit, offst, a; |
---|
1005 | unsigned long tsau_reg, tat_reg, gran, skip; |
---|
1006 | |
---|
1007 | CHECK_BASE(base,0,-1); |
---|
1008 | |
---|
1009 | mode = 0; /* silence warning */ |
---|
1010 | |
---|
1011 | switch ( as & VME_MODE_MATCH_MASK ) { |
---|
1012 | case VME_MODE_EXACT_MATCH: |
---|
1013 | mode_msk = ~0; |
---|
1014 | break; |
---|
1015 | |
---|
1016 | case VME_MODE_AS_MATCH: |
---|
1017 | if ( outbound ) |
---|
1018 | mode_msk = TSI_OTAT_ADMODE(-1) | TSI_OTAT_EN; |
---|
1019 | else |
---|
1020 | mode_msk = TSI_ITAT_AS(-1) | TSI_ITAT_EN; |
---|
1021 | break; |
---|
1022 | |
---|
1023 | default: |
---|
1024 | if ( outbound ) |
---|
1025 | mode_msk = TSI_OTAT_PGM | TSI_OTAT_SUP | TSI_OTAT_ADMODE(-1) | TSI_OTAT_EN; |
---|
1026 | else |
---|
1027 | mode_msk = TSI_ITAT_PGM | TSI_ITAT_DATA | TSI_ITAT_SUP | TSI_ITAT_USR | TSI_ITAT_AS(-1) | TSI_ITAT_EN; |
---|
1028 | break; |
---|
1029 | } |
---|
1030 | |
---|
1031 | as &= ~VME_MODE_MATCH_MASK; |
---|
1032 | |
---|
1033 | if ( outbound ? am2omode(as,&mode) : am2imode(as,&mode) ) { |
---|
1034 | uprintf(stderr, "vmeTsi148XlateAddr: invalid address space/mode argument"); |
---|
1035 | return -2; |
---|
1036 | } |
---|
1037 | |
---|
1038 | if (outbound ) { |
---|
1039 | tsau_reg = TSI_OTSAU_REG(0); |
---|
1040 | tat_reg = TSI_OTAT_REG(0); |
---|
1041 | skip = TSI_OTSAU_SPACING; |
---|
1042 | mode |= TSI_OTAT_EN; |
---|
1043 | gran = 0x10000; |
---|
1044 | } else { |
---|
1045 | tsau_reg = TSI_ITSAU_REG(0); |
---|
1046 | tat_reg = TSI_ITAT_REG(0); |
---|
1047 | skip = TSI_ITSAU_SPACING; |
---|
1048 | mode |= TSI_ITAT_EN; |
---|
1049 | gran = inboundGranularity(mode) + 1; |
---|
1050 | } |
---|
1051 | |
---|
1052 | for ( port = 0; port < TSI148_NUM_OPORTS; port++, tsau_reg += skip, tat_reg += skip ) { |
---|
1053 | |
---|
1054 | if ( (mode & mode_msk) == (TSI_RD(base, tat_reg) & mode_msk) ) { |
---|
1055 | |
---|
1056 | /* found a window with of the right mode; now check the range */ |
---|
1057 | readTriple(base, tsau_reg, &start, &limit, &offst); |
---|
1058 | limit += gran; |
---|
1059 | |
---|
1060 | if ( !reverse ) { |
---|
1061 | start += offst; |
---|
1062 | limit += offst; |
---|
1063 | offst = -offst; |
---|
1064 | } |
---|
1065 | a = aIn; |
---|
1066 | if ( aIn >= start && aIn <= limit ) { |
---|
1067 | /* found it */ |
---|
1068 | *paOut = (unsigned long)(a + offst); |
---|
1069 | return port; |
---|
1070 | } |
---|
1071 | } |
---|
1072 | } |
---|
1073 | |
---|
1074 | uprintf(stderr, "vmeTsi148XlateAddr: no matching mapping found\n"); |
---|
1075 | return -1; |
---|
1076 | } |
---|
1077 | |
---|
1078 | int |
---|
1079 | vmeTsi148XlateAddrXX( |
---|
1080 | BERegister *base, /* TSI 148 base address */ |
---|
1081 | int outbound, /* look in the outbound windows */ |
---|
1082 | int reverse, /* reverse mapping; for outbound ports: map local to VME */ |
---|
1083 | unsigned long as, /* address space */ |
---|
1084 | unsigned long aIn, /* address to look up */ |
---|
1085 | unsigned long *paOut/* where to put result */ |
---|
1086 | ) |
---|
1087 | { |
---|
1088 | int port = xlateFindPort( base, outbound, reverse, as, aIn, paOut ); |
---|
1089 | return port < 0 ? -1 : 0; |
---|
1090 | } |
---|
1091 | |
---|
1092 | int |
---|
1093 | vmeTsi148XlateAddr( |
---|
1094 | int outbound, /* look in the outbound windows */ |
---|
1095 | int reverse, /* reverse mapping; for outbound ports: map local to VME */ |
---|
1096 | unsigned long as, /* address space */ |
---|
1097 | unsigned long aIn, /* address to look up */ |
---|
1098 | unsigned long *paOut/* where to put result */ |
---|
1099 | ) |
---|
1100 | { |
---|
1101 | return vmeTsi148XlateAddrXX(THEBASE, outbound, reverse, as, aIn, paOut); |
---|
1102 | } |
---|
1103 | |
---|
1104 | |
---|
1105 | /* printk cannot format %llx */ |
---|
1106 | static void uprintfllx(FILE *f, unsigned long long v) |
---|
1107 | { |
---|
1108 | if ( v >= ((unsigned long long)1)<<32 ) |
---|
1109 | uprintf(f,"0x%lx%08lx ", (unsigned long)(v>>32), (unsigned long)(v & 0xffffffff)); |
---|
1110 | else |
---|
1111 | uprintf(f,"0x%08lx ", (unsigned long)(v & 0xffffffff)); |
---|
1112 | } |
---|
1113 | |
---|
1114 | void |
---|
1115 | vmeTsi148OutboundPortsShowXX(BERegister *base, FILE *f) |
---|
1116 | { |
---|
1117 | int port; |
---|
1118 | unsigned long mode; |
---|
1119 | char tit = 0; |
---|
1120 | |
---|
1121 | unsigned long long start, limit, offst; |
---|
1122 | |
---|
1123 | CHECK_BASE(base,0, ); |
---|
1124 | |
---|
1125 | if (!f) f=stdout; |
---|
1126 | uprintf(f,"Tsi148 Outbound Ports:\n"); |
---|
1127 | |
---|
1128 | for ( port = 0; port < TSI148_NUM_OPORTS; port++ ) { |
---|
1129 | mode = TSI_RD(base, TSI_OTAT_REG(port)); |
---|
1130 | if ( ! (TSI_OTAT_EN & mode) ) |
---|
1131 | continue; /* skip disabled ports */ |
---|
1132 | |
---|
1133 | readTriple(base, TSI_OTSAU_REG(port), &start, &limit, &offst); |
---|
1134 | |
---|
1135 | /* convert limit to size */ |
---|
1136 | limit = limit-start+0x10000; |
---|
1137 | if ( !tit ) { |
---|
1138 | uprintf(f,"Port VME-Addr Size PCI-Adrs Mode:\n"); |
---|
1139 | tit = 1; |
---|
1140 | } |
---|
1141 | uprintf(f,"%d: ", port); |
---|
1142 | uprintfllx(f,start+offst); |
---|
1143 | uprintfllx(f,limit); |
---|
1144 | uprintfllx(f,start); |
---|
1145 | switch( mode & TSI_OTAT_ADMODE(-1) ) { |
---|
1146 | case TSI_OTAT_ADMODE_A16: uprintf(f,"A16"); break; |
---|
1147 | case TSI_OTAT_ADMODE_A24: uprintf(f,"A24"); break; |
---|
1148 | case TSI_OTAT_ADMODE_A32: uprintf(f,"A32"); break; |
---|
1149 | case TSI_OTAT_ADMODE_A64: uprintf(f,"A64"); break; |
---|
1150 | case TSI_OTAT_ADMODE_CSR: uprintf(f,"CSR"); break; |
---|
1151 | default: uprintf(f,"A??"); break; |
---|
1152 | } |
---|
1153 | |
---|
1154 | if ( mode & TSI_OTAT_PGM ) uprintf(f,", PGM"); |
---|
1155 | if ( mode & TSI_OTAT_SUP ) uprintf(f,", SUP"); |
---|
1156 | if ( ! (TSI_OTAT_MRPFD & mode) ) uprintf(f,", PREFETCH"); |
---|
1157 | |
---|
1158 | switch ( mode & TSI_OTAT_DBW(-1) ) { |
---|
1159 | case TSI_OTAT_DBW(0): uprintf(f,", D16"); break; |
---|
1160 | case TSI_OTAT_DBW(1): uprintf(f,", D32"); break; |
---|
1161 | default: uprintf(f,", D??"); break; |
---|
1162 | } |
---|
1163 | |
---|
1164 | switch( mode & TSI_OTAT_TM(-1) ) { |
---|
1165 | case TSI_OTAT_TM(0): uprintf(f,", SCT"); break; |
---|
1166 | case TSI_OTAT_TM(1): uprintf(f,", BLT"); break; |
---|
1167 | case TSI_OTAT_TM(2): uprintf(f,", MBLT"); break; |
---|
1168 | case TSI_OTAT_TM(3): uprintf(f,", 2eVME"); break; |
---|
1169 | case TSI_OTAT_TM(4): uprintf(f,", 2eSST"); break; |
---|
1170 | case TSI_OTAT_TM(5): uprintf(f,", 2eSST_BCST"); break; |
---|
1171 | default: uprintf(f," TM??"); break; |
---|
1172 | } |
---|
1173 | |
---|
1174 | uprintf(f,"\n"); |
---|
1175 | } |
---|
1176 | } |
---|
1177 | |
---|
1178 | void |
---|
1179 | vmeTsi148OutboundPortsShow(FILE *f) |
---|
1180 | { |
---|
1181 | vmeTsi148OutboundPortsShowXX(THEBASE, f); |
---|
1182 | } |
---|
1183 | |
---|
1184 | void |
---|
1185 | vmeTsi148InboundPortsShowXX(BERegister *base, FILE *f) |
---|
1186 | { |
---|
1187 | int port; |
---|
1188 | unsigned long mode; |
---|
1189 | char tit = 0; |
---|
1190 | |
---|
1191 | unsigned long long start, limit, offst; |
---|
1192 | |
---|
1193 | CHECK_BASE(base,0, ); |
---|
1194 | |
---|
1195 | if (!f) f=stdout; |
---|
1196 | uprintf(f,"Tsi148 Inbound Ports:\n"); |
---|
1197 | |
---|
1198 | for ( port = 0; port < TSI148_NUM_IPORTS; port++ ) { |
---|
1199 | mode = TSI_RD(base, TSI_ITAT_REG(port)); |
---|
1200 | if ( ! (TSI_ITAT_EN & mode) ) |
---|
1201 | continue; /* skip disabled ports */ |
---|
1202 | |
---|
1203 | readTriple(base, TSI_ITSAU_REG(port), &start, &limit, &offst); |
---|
1204 | |
---|
1205 | /* convert limit to size */ |
---|
1206 | limit = limit - start + inboundGranularity(mode) + 1; |
---|
1207 | if ( !tit ) { |
---|
1208 | uprintf(f,"Port VME-Addr Size PCI-Adrs Mode:\n"); |
---|
1209 | tit = 1; |
---|
1210 | } |
---|
1211 | uprintf(f,"%d: ", port); |
---|
1212 | uprintfllx(f,start); |
---|
1213 | uprintfllx(f,limit); |
---|
1214 | uprintfllx(f,start+offst); |
---|
1215 | switch( mode & TSI_ITAT_AS(-1) ) { |
---|
1216 | case TSI_ITAT_ADMODE_A16: uprintf(f,"A16"); break; |
---|
1217 | case TSI_ITAT_ADMODE_A24: uprintf(f,"A24"); break; |
---|
1218 | case TSI_ITAT_ADMODE_A32: uprintf(f,"A32"); break; |
---|
1219 | case TSI_ITAT_ADMODE_A64: uprintf(f,"A64"); break; |
---|
1220 | default: uprintf(f,"A??"); break; |
---|
1221 | } |
---|
1222 | |
---|
1223 | if ( mode & TSI_ITAT_PGM ) uprintf(f,", PGM"); |
---|
1224 | if ( mode & TSI_ITAT_DATA ) uprintf(f,", DAT"); |
---|
1225 | if ( mode & TSI_ITAT_SUP ) uprintf(f,", SUP"); |
---|
1226 | if ( mode & TSI_ITAT_USR ) uprintf(f,", USR"); |
---|
1227 | |
---|
1228 | if ( mode & TSI_ITAT_2eSSTB ) uprintf(f,", 2eSSTB"); |
---|
1229 | if ( mode & TSI_ITAT_2eSST ) uprintf(f,", 2eSST"); |
---|
1230 | if ( mode & TSI_ITAT_2eVME ) uprintf(f,", 2eVME"); |
---|
1231 | if ( mode & TSI_ITAT_MBLT ) uprintf(f,", MBLT"); |
---|
1232 | if ( mode & TSI_ITAT_BLT ) uprintf(f,", BLT"); |
---|
1233 | |
---|
1234 | uprintf(f,"\n"); |
---|
1235 | } |
---|
1236 | } |
---|
1237 | |
---|
1238 | void |
---|
1239 | vmeTsi148InboundPortsShow(FILE *f) |
---|
1240 | { |
---|
1241 | vmeTsi148InboundPortsShowXX(THEBASE, f); |
---|
1242 | } |
---|
1243 | |
---|
1244 | |
---|
1245 | void |
---|
1246 | vmeTsi148DisableAllInboundPortsXX(BERegister *base) |
---|
1247 | { |
---|
1248 | int port; |
---|
1249 | |
---|
1250 | for ( port = 0; port < TSI148_NUM_IPORTS; port++ ) |
---|
1251 | if ( disableTsiPort(base, 0, port) ) |
---|
1252 | break; |
---|
1253 | } |
---|
1254 | |
---|
1255 | void |
---|
1256 | vmeTsi148DisableAllInboundPorts(void) |
---|
1257 | { |
---|
1258 | vmeTsi148DisableAllInboundPortsXX(THEBASE); |
---|
1259 | } |
---|
1260 | |
---|
1261 | void |
---|
1262 | vmeTsi148DisableAllOutboundPortsXX(BERegister *base) |
---|
1263 | { |
---|
1264 | int port; |
---|
1265 | |
---|
1266 | for ( port = 0; port < TSI148_NUM_IPORTS; port++ ) |
---|
1267 | if ( disableTsiPort(base, 1, port) ) |
---|
1268 | break; |
---|
1269 | } |
---|
1270 | |
---|
1271 | void |
---|
1272 | vmeTsi148DisableAllOutboundPorts(void) |
---|
1273 | { |
---|
1274 | vmeTsi148DisableAllOutboundPortsXX(THEBASE); |
---|
1275 | } |
---|
1276 | |
---|
1277 | |
---|
1278 | /* Map internal register block to VME */ |
---|
1279 | |
---|
1280 | int |
---|
1281 | vmeTsi148MapCRGXX(BERegister *b, uint32_t vme_base, uint32_t as ) |
---|
1282 | { |
---|
1283 | uint32_t mode; |
---|
1284 | |
---|
1285 | CHECK_BASE( b, 0, -1 ); |
---|
1286 | |
---|
1287 | if ( vmeTsi148RegPort > -1 && ! vmeTsi148RegCSR ) { |
---|
1288 | uprintf(stderr,"vmeTsi148: CRG already mapped and in use by interrupt manager\n"); |
---|
1289 | return -1; |
---|
1290 | } |
---|
1291 | |
---|
1292 | /* enable all, SUP/USR/PGM/DATA accesses */ |
---|
1293 | mode = TSI_CRGAT_EN | TSI_CRGAT_SUP | TSI_CRGAT_USR | TSI_CRGAT_PGM | TSI_CRGAT_DATA; |
---|
1294 | |
---|
1295 | if ( VME_AM_IS_SHORT(as) ) { |
---|
1296 | mode |= TSI_CRGAT_A16; |
---|
1297 | } else |
---|
1298 | if ( VME_AM_IS_STD(as) ) { |
---|
1299 | mode |= TSI_CRGAT_A24; |
---|
1300 | } else |
---|
1301 | if ( VME_AM_IS_EXT(as) ) { |
---|
1302 | mode |= TSI_CRGAT_A32; |
---|
1303 | } else { |
---|
1304 | return -2; |
---|
1305 | } |
---|
1306 | |
---|
1307 | /* map CRG to VME bus */ |
---|
1308 | TSI_WR( b, TSI_CBAL_REG, (vme_base & ~(TSI_CRG_SIZE-1))); |
---|
1309 | TSI_WR( b, TSI_CRGAT_REG, mode ); |
---|
1310 | |
---|
1311 | return 0; |
---|
1312 | } |
---|
1313 | |
---|
1314 | int |
---|
1315 | vmeTsi148MapCRG(uint32_t vme_base, uint32_t as ) |
---|
1316 | { |
---|
1317 | return vmeTsi148MapCRGXX( THEBASE, vme_base, as ); |
---|
1318 | } |
---|
1319 | |
---|
1320 | /* Interrupt Subsystem */ |
---|
1321 | |
---|
1322 | typedef struct |
---|
1323 | IRQEntryRec_ { |
---|
1324 | VmeTsi148ISR isr; |
---|
1325 | void *usrData; |
---|
1326 | } IRQEntryRec, *IRQEntry; |
---|
1327 | |
---|
1328 | static IRQEntry irqHdlTbl[TSI_NUM_INT_VECS]={0}; |
---|
1329 | |
---|
1330 | int vmeTsi148IrqMgrInstalled = 0; |
---|
1331 | int vmeTsi148RegPort = -1; |
---|
1332 | int vmeTsi148RegCSR = 0; |
---|
1333 | BERegister *vmeTsi148RegBase = 0; |
---|
1334 | |
---|
1335 | static volatile unsigned long wire_mask[TSI_NUM_WIRES] = {0}; |
---|
1336 | /* wires are offset by 1 so we can initialize the wire table to all zeros */ |
---|
1337 | static int tsi_wire[TSI_NUM_WIRES] = {0}; |
---|
1338 | |
---|
1339 | /* how should we iack a given level, 1,2,4 bytes? */ |
---|
1340 | static unsigned char tsi_iack_width[7] = { |
---|
1341 | 1,1,1,1,1,1,1 |
---|
1342 | }; |
---|
1343 | |
---|
1344 | /* map universe compatible vector # to Tsi slot (which maps to bit layout in stat/enable/... regs) */ |
---|
1345 | static int uni2tsi_vec_map[TSI_NUM_INT_VECS-256] = { |
---|
1346 | /* 256 no VOWN interrupt */ -1, |
---|
1347 | /* TSI_DMA_INT_VEC 257 */ 256 + 24 - 8, |
---|
1348 | /* TSI_LERR_INT_VEC 258 */ 256 + 13 - 8, |
---|
1349 | /* TSI_VERR_INT_VEC 259 */ 256 + 12 - 8, |
---|
1350 | /* 260 is reserved */ -1, |
---|
1351 | /* TSI_VME_SW_IACK_INT_VEC 261 */ 256 + 10 - 8, |
---|
1352 | /* 262 no PCI SW IRQ */ -1, |
---|
1353 | /* TSI_SYSFAIL_INT_VEC 263 */ 256 + 9 - 8, |
---|
1354 | /* TSI_ACFAIL_INT_VEC 264 */ 256 + 8 - 8, |
---|
1355 | /* TSI_MBOX0_INT_VEC 265 */ 256 + 16 - 8, |
---|
1356 | /* TSI_MBOX1_INT_VEC 266 */ 256 + 17 - 8, |
---|
1357 | /* TSI_MBOX2_INT_VEC 267 */ 256 + 18 - 8, |
---|
1358 | /* TSI_MBOX3_INT_VEC 268 */ 256 + 19 - 8, |
---|
1359 | /* TSI_LM0_INT_VEC 269 */ 256 + 20 - 8, |
---|
1360 | /* TSI_LM1_INT_VEC 270 */ 256 + 21 - 8, |
---|
1361 | /* TSI_LM2_INT_VEC 271 */ 256 + 22 - 8, |
---|
1362 | /* TSI_LM3_INT_VEC 272 */ 256 + 23 - 8, |
---|
1363 | /* New vectors; only on TSI148 */ |
---|
1364 | /* TSI_VIES_INT_VEC 273 */ 256 + 11 - 8, |
---|
1365 | /* TSI_DMA1_INT_VEC 274 */ 256 + 25 - 8, |
---|
1366 | }; |
---|
1367 | |
---|
1368 | /* and the reverse; map tsi bit number to universe compatible 'special' vector number */ |
---|
1369 | static int tsi2uni_vec_map[TSI_NUM_INT_VECS - 256] = { |
---|
1370 | TSI_ACFAIL_INT_VEC, |
---|
1371 | TSI_SYSFAIL_INT_VEC, |
---|
1372 | TSI_VME_SW_IACK_INT_VEC, |
---|
1373 | TSI_VIES_INT_VEC, |
---|
1374 | TSI_VERR_INT_VEC, |
---|
1375 | TSI_LERR_INT_VEC, |
---|
1376 | -1, |
---|
1377 | -1, |
---|
1378 | TSI_MBOX0_INT_VEC, |
---|
1379 | TSI_MBOX1_INT_VEC, |
---|
1380 | TSI_MBOX2_INT_VEC, |
---|
1381 | TSI_MBOX3_INT_VEC, |
---|
1382 | TSI_LM0_INT_VEC, |
---|
1383 | TSI_LM1_INT_VEC, |
---|
1384 | TSI_LM2_INT_VEC, |
---|
1385 | TSI_LM3_INT_VEC, |
---|
1386 | TSI_DMA_INT_VEC, |
---|
1387 | TSI_DMA1_INT_VEC, |
---|
1388 | -1, |
---|
1389 | }; |
---|
1390 | |
---|
1391 | static inline int |
---|
1392 | uni2tsivec(int v) |
---|
1393 | { |
---|
1394 | if ( v < 0 || v >= TSI_NUM_INT_VECS ) |
---|
1395 | return -1; |
---|
1396 | return v < 256 ? v : uni2tsi_vec_map[v-256]; |
---|
1397 | } |
---|
1398 | |
---|
1399 | static int |
---|
1400 | lvl2bitno(unsigned int level) |
---|
1401 | { |
---|
1402 | if ( level >= 256 ) |
---|
1403 | return uni2tsivec(level) + 8 - 256; |
---|
1404 | else if ( level < 8 && level > 0 ) |
---|
1405 | return level; |
---|
1406 | return -1; |
---|
1407 | } |
---|
1408 | |
---|
1409 | int |
---|
1410 | vmeTsi148IntRoute(unsigned int level, unsigned int pin) |
---|
1411 | { |
---|
1412 | int i; |
---|
1413 | unsigned long mask, shift, mapreg, flags, wire; |
---|
1414 | |
---|
1415 | if ( pin >= TSI_NUM_WIRES || ! tsi_wire[pin] || !vmeTsi148IrqMgrInstalled ) |
---|
1416 | return -1; |
---|
1417 | |
---|
1418 | if ( level >= 256 ) { |
---|
1419 | if ( (i = uni2tsivec(level)) < 0 ) |
---|
1420 | return -1; |
---|
1421 | shift = 8 + (i-256); |
---|
1422 | } else if ( 1 <= level && level <=7 ) { |
---|
1423 | shift = level; |
---|
1424 | } else { |
---|
1425 | return -1; /* invalid level */ |
---|
1426 | } |
---|
1427 | |
---|
1428 | mask = 1<<shift; |
---|
1429 | |
---|
1430 | /* calculate the mapping register and contents */ |
---|
1431 | if ( shift < 16 ) { |
---|
1432 | mapreg = TSI_INTM2_REG; |
---|
1433 | } else if ( shift < 32 ) { |
---|
1434 | shift -= 16; |
---|
1435 | mapreg = TSI_INTM1_REG; |
---|
1436 | } else { |
---|
1437 | return -1; |
---|
1438 | } |
---|
1439 | |
---|
1440 | shift <<=1; |
---|
1441 | |
---|
1442 | /* wires are offset by 1 so we can initialize the wire table to all zeros */ |
---|
1443 | wire = (tsi_wire[pin]-1) << shift; |
---|
1444 | |
---|
1445 | rtems_interrupt_disable(flags); |
---|
1446 | |
---|
1447 | for ( i = 0; i<TSI_NUM_WIRES; i++ ) { |
---|
1448 | wire_mask[i] &= ~mask; |
---|
1449 | } |
---|
1450 | wire_mask[pin] |= mask; |
---|
1451 | |
---|
1452 | mask = TSI_RD(THEBASE, mapreg) & ~ (0x3<<shift); |
---|
1453 | mask |= wire; |
---|
1454 | TSI_WR( THEBASE, mapreg, mask ); |
---|
1455 | |
---|
1456 | rtems_interrupt_enable(flags); |
---|
1457 | return 0; |
---|
1458 | } |
---|
1459 | |
---|
1460 | VmeTsi148ISR |
---|
1461 | vmeTsi148ISRGet(unsigned long vector, void **parg) |
---|
1462 | { |
---|
1463 | VmeTsi148ISR rval = 0; |
---|
1464 | unsigned long flags; |
---|
1465 | volatile IRQEntry *p; |
---|
1466 | int v = uni2tsivec(vector); |
---|
1467 | |
---|
1468 | |
---|
1469 | if ( v < 0 ) |
---|
1470 | return rval; |
---|
1471 | |
---|
1472 | p = irqHdlTbl + v; |
---|
1473 | |
---|
1474 | rtems_interrupt_disable(flags); |
---|
1475 | if ( *p ) { |
---|
1476 | if ( parg ) |
---|
1477 | *parg = (*p)->usrData; |
---|
1478 | rval = (*p)->isr; |
---|
1479 | } |
---|
1480 | rtems_interrupt_enable(flags); |
---|
1481 | |
---|
1482 | return rval; |
---|
1483 | } |
---|
1484 | |
---|
1485 | static void |
---|
1486 | tsiVMEISR(rtems_irq_hdl_param arg) |
---|
1487 | { |
---|
1488 | int pin = (int)arg; |
---|
1489 | BERegister *b = THEBASE; |
---|
1490 | IRQEntry ip; |
---|
1491 | unsigned long msk,lintstat,vector, vecarg; |
---|
1492 | int lvl; |
---|
1493 | |
---|
1494 | /* only handle interrupts routed to this pin */ |
---|
1495 | |
---|
1496 | /* NOTE: we read the status register over VME, thus flushing the FIFO |
---|
1497 | * where the user ISR possibly left write commands to clear |
---|
1498 | * the interrupt condition at the device. |
---|
1499 | * This is very important - otherwise, the IRQ level may still be |
---|
1500 | * asserted and we would detect an interrupt here but the subsequent |
---|
1501 | * IACK would fail since the write operation was flushed to the |
---|
1502 | * device in the mean time. |
---|
1503 | */ |
---|
1504 | while ( (lintstat = (TSI_RD(vmeTsi148RegBase, TSI_INTS_REG) & wire_mask[pin])) ) { |
---|
1505 | |
---|
1506 | /* bit 0 is never set since it is never set in wire_mask */ |
---|
1507 | |
---|
1508 | do { |
---|
1509 | /* simplicity is king; just handle them in MSB to LSB order; reserved bits read as 0 */ |
---|
1510 | #ifdef __PPC__ |
---|
1511 | asm volatile("cntlzw %0, %1":"=r"(lvl):"r"(lintstat)); |
---|
1512 | lvl = 31-lvl; |
---|
1513 | msk = 1<<lvl; |
---|
1514 | #else |
---|
1515 | { static unsigned long m[] = { |
---|
1516 | 0xffff0000, 0xff00ff00, 0xf0f0f0f0, 0xcccccccc, 0xaaaaaaaa |
---|
1517 | }; |
---|
1518 | int i; |
---|
1519 | unsigned tmp; |
---|
1520 | |
---|
1521 | /* lintstat has already been checked... |
---|
1522 | if ( !lintstat ) { |
---|
1523 | lvl = -1; msk = 0; |
---|
1524 | } else |
---|
1525 | */ |
---|
1526 | for ( i=0, lvl=0, msk = lintstat; i<5; i++ ) { |
---|
1527 | lvl <<= 1; |
---|
1528 | if ( (tmp = msk & m[i]) ) { |
---|
1529 | lvl++; |
---|
1530 | msk = tmp; |
---|
1531 | } else |
---|
1532 | msk = msk & ~m[i]; |
---|
1533 | } |
---|
1534 | } |
---|
1535 | #endif |
---|
1536 | |
---|
1537 | if ( lvl > 7 ) { |
---|
1538 | /* clear this interrupt level */ |
---|
1539 | TSI_WR(b, TSI_INTC_REG, msk); |
---|
1540 | vector = 256 + lvl - 8; |
---|
1541 | vecarg = tsi2uni_vec_map[lvl-8]; |
---|
1542 | } else { |
---|
1543 | /* need to do get the vector for this level */ |
---|
1544 | switch ( tsi_iack_width[lvl-1] ) { |
---|
1545 | default: |
---|
1546 | case 1: |
---|
1547 | vector = TSI_RD8(b, TSI_VIACK_1_REG - 4 + (lvl<<2) + 3); |
---|
1548 | break; |
---|
1549 | |
---|
1550 | case 2: |
---|
1551 | vector = TSI_RD16(b, TSI_VIACK_1_REG - 4 + (lvl<<2) + 2); |
---|
1552 | break; |
---|
1553 | |
---|
1554 | case 4: |
---|
1555 | vector = TSI_RD(b, TSI_VIACK_1_REG - 4 + (lvl<<2)); |
---|
1556 | break; |
---|
1557 | } |
---|
1558 | vecarg = vector; |
---|
1559 | } |
---|
1560 | |
---|
1561 | if ( !(ip=irqHdlTbl[vector])) { |
---|
1562 | /* TODO: log error message - RTEMS has no logger :-( */ |
---|
1563 | vmeTsi148IntDisable(lvl); |
---|
1564 | printk("vmeTsi148 ISR: ERROR: no handler registered (level %i) IACK 0x%08lx -- DISABLING level %i\n", |
---|
1565 | lvl, vector, lvl); |
---|
1566 | } else { |
---|
1567 | /* dispatch handler, it must clear the IRQ at the device */ |
---|
1568 | ip->isr(ip->usrData, vecarg); |
---|
1569 | /* convenience for disobedient users who don't use in_xxx/out_xxx; make |
---|
1570 | * sure we order the subsequent read from the status register after |
---|
1571 | * their business. |
---|
1572 | */ |
---|
1573 | iobarrier_rw(); |
---|
1574 | } |
---|
1575 | } while ( (lintstat &= ~msk) ); |
---|
1576 | /* check if a new irq is pending already */ |
---|
1577 | } |
---|
1578 | } |
---|
1579 | |
---|
1580 | |
---|
1581 | static void |
---|
1582 | my_no_op(const rtems_irq_connect_data * arg) |
---|
1583 | {} |
---|
1584 | |
---|
1585 | static int |
---|
1586 | my_isOn(const rtems_irq_connect_data *arg) |
---|
1587 | { |
---|
1588 | return (int)(TSI_RD(THEBASE, TSI_INTEO_REG) & TSI_RD(THEBASE, TSI_INTEN_REG)); |
---|
1589 | } |
---|
1590 | |
---|
1591 | static void |
---|
1592 | connectIsr(int shared, rtems_irq_hdl isr, int pic_line, int slot) |
---|
1593 | { |
---|
1594 | rtems_irq_connect_data xx; |
---|
1595 | xx.on = my_no_op; /* at _least_ they could check for a 0 pointer */ |
---|
1596 | xx.off = my_no_op; |
---|
1597 | xx.isOn = my_isOn; |
---|
1598 | xx.hdl = isr; |
---|
1599 | xx.handle = (rtems_irq_hdl_param)slot; |
---|
1600 | xx.name = pic_line; |
---|
1601 | |
---|
1602 | if ( shared ) { |
---|
1603 | #if BSP_SHARED_HANDLER_SUPPORT > 0 |
---|
1604 | if (!BSP_install_rtems_shared_irq_handler(&xx)) |
---|
1605 | rtems_panic("unable to install vmeTsi148 shared irq handler"); |
---|
1606 | #else |
---|
1607 | uprintf(stderr,"vmeTsi148: WARNING: your BSP doesn't support sharing interrupts\n"); |
---|
1608 | if (!BSP_install_rtems_irq_handler(&xx)) |
---|
1609 | rtems_panic("unable to install vmeTsi148 irq handler"); |
---|
1610 | #endif |
---|
1611 | } else { |
---|
1612 | if (!BSP_install_rtems_irq_handler(&xx)) |
---|
1613 | rtems_panic("unable to install vmeTsi148 irq handler"); |
---|
1614 | } |
---|
1615 | } |
---|
1616 | |
---|
1617 | int |
---|
1618 | vmeTsi148InstallIrqMgrAlt(int shared, int tsi_pin0, int pic_pin0, ...) |
---|
1619 | { |
---|
1620 | int rval; |
---|
1621 | va_list ap; |
---|
1622 | va_start(ap, pic_pin0); |
---|
1623 | rval = vmeTsi148InstallIrqMgrVa(shared, tsi_pin0, pic_pin0, ap); |
---|
1624 | va_end(ap); |
---|
1625 | return rval; |
---|
1626 | } |
---|
1627 | |
---|
1628 | #ifndef BSP_EARLY_PROBE_VME |
---|
1629 | #define BSP_EARLY_PROBE_VME(addr) \ |
---|
1630 | ( \ |
---|
1631 | vmeTsi148ClearVMEBusErrorsXX( THEBASE, 0 ), \ |
---|
1632 | ( ((PCI_DEVICE_TSI148 << 16) | PCI_VENDOR_TUNDRA ) == TSI_LE_RD32( ((BERegister*)(addr)), 0 ) \ |
---|
1633 | && 0 == vmeTsi148ClearVMEBusErrorsXX( THEBASE, 0 ) ) \ |
---|
1634 | ) |
---|
1635 | #endif |
---|
1636 | |
---|
1637 | /* Check if there is a vme address/as is mapped in any of the outbound windows |
---|
1638 | * and look for the PCI vendordevice ID there. |
---|
1639 | * RETURNS: -1 on error (no mapping or probe failure), outbound window # (0..7) |
---|
1640 | * on success. Address translated into CPU address is returned in *pcpu_addr. |
---|
1641 | */ |
---|
1642 | static int |
---|
1643 | mappedAndProbed(unsigned long vme_addr, unsigned as, unsigned long *pcpu_addr) |
---|
1644 | { |
---|
1645 | int j; |
---|
1646 | char *regtype = (as & VME_AM_MASK) == VME_AM_CSR ? "CSR" : "CRG"; |
---|
1647 | |
---|
1648 | /* try to find mapping */ |
---|
1649 | if ( 0 > (j = xlateFindPort( |
---|
1650 | THEBASE, |
---|
1651 | 1, 0, |
---|
1652 | as | VME_MODE_AS_MATCH, |
---|
1653 | vme_addr, |
---|
1654 | pcpu_addr ) ) ) { |
---|
1655 | uprintf(stderr,"vmeTsi148 - Unable to find mapping for %s VME base (0x%08x)\n", regtype, vme_addr); |
---|
1656 | uprintf(stderr," in outbound windows.\n"); |
---|
1657 | } |
---|
1658 | else { |
---|
1659 | /* found a slot number; probe it */ |
---|
1660 | *pcpu_addr = BSP_PCI2LOCAL_ADDR( *pcpu_addr ); |
---|
1661 | if ( BSP_EARLY_PROBE_VME(*pcpu_addr) ) { |
---|
1662 | uprintf(stderr,"vmeTsi148 - IRQ manager using VME %s to flush FIFO\n", regtype); |
---|
1663 | return j; |
---|
1664 | } else { |
---|
1665 | uprintf(stderr,"vmeTsi148 - Found slot info but detection of tsi148 in VME %s space failed\n", regtype); |
---|
1666 | } |
---|
1667 | } |
---|
1668 | return -1; |
---|
1669 | } |
---|
1670 | |
---|
1671 | int |
---|
1672 | vmeTsi148InstallIrqMgrVa(int shared, int tsi_pin0, int pic_pin0, va_list ap) |
---|
1673 | { |
---|
1674 | int i,j, specialPin, tsi_pin[TSI_NUM_WIRES+1], pic_pin[TSI_NUM_WIRES]; |
---|
1675 | unsigned long cpu_base, vme_reg_base; |
---|
1676 | |
---|
1677 | if (vmeTsi148IrqMgrInstalled) return -4; |
---|
1678 | |
---|
1679 | /* check parameters */ |
---|
1680 | |
---|
1681 | if ( tsi_pin0 < 0 || tsi_pin0 > 3 ) return -1; |
---|
1682 | |
---|
1683 | tsi_pin[0] = tsi_pin0; |
---|
1684 | pic_pin[0] = pic_pin0 < 0 ? devs[0].irqLine : pic_pin0; |
---|
1685 | i = 1; |
---|
1686 | while ( (tsi_pin[i] = va_arg(ap, int)) >= 0 ) { |
---|
1687 | |
---|
1688 | if ( i >= TSI_NUM_WIRES ) { |
---|
1689 | return -5; |
---|
1690 | } |
---|
1691 | |
---|
1692 | pic_pin[i] = va_arg(ap,int); |
---|
1693 | |
---|
1694 | if ( tsi_pin[i] > 3 ) return -2; |
---|
1695 | if ( pic_pin[i] < 0 ) return -3; |
---|
1696 | i++; |
---|
1697 | } |
---|
1698 | |
---|
1699 | /* all routings must be different */ |
---|
1700 | for ( i=0; tsi_pin[i] >= 0; i++ ) { |
---|
1701 | for ( j=i+1; tsi_pin[j] >= 0; j++ ) { |
---|
1702 | if ( tsi_pin[j] == tsi_pin[i] ) return -6; |
---|
1703 | if ( pic_pin[j] == pic_pin[i] ) return -7; |
---|
1704 | } |
---|
1705 | } |
---|
1706 | |
---|
1707 | i = -1; |
---|
1708 | |
---|
1709 | /* first try VME CSR space; do we have a base address set ? */ |
---|
1710 | |
---|
1711 | uprintf(stderr,"vmeTsi148 IRQ manager: looking for registers on VME...\n"); |
---|
1712 | |
---|
1713 | if ( ( i = ((TSI_RD( THEBASE, TSI_CBAR_REG ) & 0xff) >> 3) ) > 0 ) { |
---|
1714 | uprintf(stderr,"Trying to find CSR on VME...\n"); |
---|
1715 | vme_reg_base = i*0x80000 + TSI_CSR_OFFSET; |
---|
1716 | i = mappedAndProbed( vme_reg_base, VME_AM_CSR , &cpu_base); |
---|
1717 | if ( i >= 0 ) |
---|
1718 | vmeTsi148RegCSR = 1; |
---|
1719 | } else { |
---|
1720 | i = -1; |
---|
1721 | } |
---|
1722 | |
---|
1723 | if ( -1 == i ) { |
---|
1724 | |
---|
1725 | uprintf(stderr,"Trying to find CRG on VME...\n"); |
---|
1726 | |
---|
1727 | /* Next we see if the CRG block is mapped to VME */ |
---|
1728 | |
---|
1729 | if ( (TSI_CRGAT_EN & (j = TSI_RD( THEBASE, TSI_CRGAT_REG ))) ) { |
---|
1730 | switch ( j & TSI_CRGAT_AS_MSK ) { |
---|
1731 | case TSI_CRGAT_A16 : i = VME_AM_SUP_SHORT_IO; break; |
---|
1732 | case TSI_CRGAT_A24 : i = VME_AM_STD_SUP_DATA; break; |
---|
1733 | case TSI_CRGAT_A32 : i = VME_AM_EXT_SUP_DATA; break; |
---|
1734 | default: |
---|
1735 | break; |
---|
1736 | } |
---|
1737 | vme_reg_base = TSI_RD( THEBASE, TSI_CBAL_REG ) & ~ (TSI_CRG_SIZE - 1); |
---|
1738 | } |
---|
1739 | |
---|
1740 | if ( -1 == i ) { |
---|
1741 | } else { |
---|
1742 | i = mappedAndProbed( vme_reg_base, (i & VME_AM_MASK), &cpu_base ); |
---|
1743 | } |
---|
1744 | } |
---|
1745 | |
---|
1746 | if ( i < 0 ) { |
---|
1747 | uprintf(stderr,"vmeTsi148 IRQ manager - BSP configuration error: registers not found on VME\n"); |
---|
1748 | uprintf(stderr,"(should open outbound window to CSR space or map CRG [vmeTsi148MapCRG()])\n"); |
---|
1749 | uprintf(stderr,"Falling back to PCI but you might experience spurious VME interrupts; read a register\n"); |
---|
1750 | uprintf(stderr,"back from user ISR to flush posted-write FIFO as a work-around\n"); |
---|
1751 | cpu_base = (unsigned long)THEBASE; |
---|
1752 | i = -1; |
---|
1753 | } |
---|
1754 | |
---|
1755 | vmeTsi148RegBase = (BERegister*)cpu_base; |
---|
1756 | vmeTsi148RegPort = i; |
---|
1757 | |
---|
1758 | /* give them a chance to override buggy PCI info */ |
---|
1759 | if ( pic_pin[0] >= 0 && devs[0].irqLine != pic_pin[0] ) { |
---|
1760 | uprintf(stderr,"Overriding main IRQ line PCI info with %d\n", |
---|
1761 | pic_pin[0]); |
---|
1762 | devs[0].irqLine = pic_pin[0]; |
---|
1763 | } |
---|
1764 | |
---|
1765 | for ( i = 0; tsi_pin[i] >= 0; i++ ) { |
---|
1766 | /* offset wire # by one so we can initialize to 0 == invalid */ |
---|
1767 | tsi_wire[i] = tsi_pin[i] + 1; |
---|
1768 | connectIsr(shared, tsiVMEISR, pic_pin[i], i); |
---|
1769 | } |
---|
1770 | |
---|
1771 | specialPin = tsi_pin[1] >= 0 ? 1 : 0; |
---|
1772 | |
---|
1773 | /* setup routing */ |
---|
1774 | |
---|
1775 | /* IntRoute checks for mgr being installed */ |
---|
1776 | vmeTsi148IrqMgrInstalled=1; |
---|
1777 | |
---|
1778 | /* route 7 VME irqs to first / 'normal' pin */ |
---|
1779 | for ( i=1; i<8; i++ ) |
---|
1780 | vmeTsi148IntRoute( i, 0 ); |
---|
1781 | for ( i=TSI_DMA_INT_VEC; i<TSI_NUM_INT_VECS; i++ ) |
---|
1782 | vmeTsi148IntRoute( i, specialPin ); |
---|
1783 | |
---|
1784 | for ( i = 0; i<TSI_NUM_WIRES; i++ ) { |
---|
1785 | /* remember (for unloading the driver) */ |
---|
1786 | devs[0].pic_pin[i] = ( ( tsi_pin[i] >=0 ) ? pic_pin[i] : -1 ); |
---|
1787 | } |
---|
1788 | |
---|
1789 | return 0; |
---|
1790 | } |
---|
1791 | |
---|
1792 | int |
---|
1793 | vmeTsi148InstallISR(unsigned long vector, VmeTsi148ISR hdl, void *arg) |
---|
1794 | { |
---|
1795 | IRQEntry ip; |
---|
1796 | int v; |
---|
1797 | unsigned long flags; |
---|
1798 | volatile IRQEntry *p; |
---|
1799 | |
---|
1800 | if ( !vmeTsi148IrqMgrInstalled || (v = uni2tsivec(vector)) < 0 ) |
---|
1801 | return -1; |
---|
1802 | |
---|
1803 | p = irqHdlTbl + v; |
---|
1804 | |
---|
1805 | if (*p || !(ip=(IRQEntry)malloc(sizeof(IRQEntryRec)))) |
---|
1806 | return -1; |
---|
1807 | |
---|
1808 | ip->isr=hdl; |
---|
1809 | ip->usrData=arg; |
---|
1810 | |
---|
1811 | rtems_interrupt_disable(flags); |
---|
1812 | if (*p) { |
---|
1813 | rtems_interrupt_enable(flags); |
---|
1814 | free(ip); |
---|
1815 | return -1; |
---|
1816 | } |
---|
1817 | *p = ip; |
---|
1818 | rtems_interrupt_enable(flags); |
---|
1819 | return 0; |
---|
1820 | } |
---|
1821 | |
---|
1822 | int |
---|
1823 | vmeTsi148RemoveISR(unsigned long vector, VmeTsi148ISR hdl, void *arg) |
---|
1824 | { |
---|
1825 | int v; |
---|
1826 | IRQEntry ip; |
---|
1827 | unsigned long flags; |
---|
1828 | volatile IRQEntry *p; |
---|
1829 | |
---|
1830 | if ( !vmeTsi148IrqMgrInstalled || (v = uni2tsivec(vector)) < 0 ) |
---|
1831 | return -1; |
---|
1832 | |
---|
1833 | p = irqHdlTbl + v; |
---|
1834 | |
---|
1835 | rtems_interrupt_disable(flags); |
---|
1836 | ip = *p; |
---|
1837 | if ( !ip || ip->isr!=hdl || ip->usrData!=arg ) { |
---|
1838 | rtems_interrupt_enable(flags); |
---|
1839 | return -1; |
---|
1840 | } |
---|
1841 | *p = 0; |
---|
1842 | rtems_interrupt_enable(flags); |
---|
1843 | |
---|
1844 | free(ip); |
---|
1845 | return 0; |
---|
1846 | } |
---|
1847 | |
---|
1848 | static int |
---|
1849 | intDoEnDis(unsigned int level, int dis) |
---|
1850 | { |
---|
1851 | BERegister *b = THEBASE; |
---|
1852 | unsigned long flags, v; |
---|
1853 | int shift; |
---|
1854 | |
---|
1855 | if ( ! vmeTsi148IrqMgrInstalled || (shift = lvl2bitno(level)) < 0 ) |
---|
1856 | return -1; |
---|
1857 | |
---|
1858 | v = 1<<shift; |
---|
1859 | |
---|
1860 | if ( !dis ) |
---|
1861 | return (int)(v & TSI_RD(b, TSI_INTEO_REG) & TSI_RD(b, TSI_INTEN_REG)) ? 1 : 0; |
---|
1862 | |
---|
1863 | rtems_interrupt_disable(flags); |
---|
1864 | if ( dis<0 ) { |
---|
1865 | TSI_WR(b, TSI_INTEN_REG, TSI_RD(b, TSI_INTEN_REG) & ~v); |
---|
1866 | TSI_WR(b, TSI_INTEO_REG, TSI_RD(b, TSI_INTEO_REG) & ~v); |
---|
1867 | } else { |
---|
1868 | TSI_WR(b, TSI_INTEN_REG, TSI_RD(b, TSI_INTEN_REG) | v); |
---|
1869 | TSI_WR(b, TSI_INTEO_REG, TSI_RD(b, TSI_INTEO_REG) | v); |
---|
1870 | } |
---|
1871 | rtems_interrupt_enable(flags); |
---|
1872 | return 0; |
---|
1873 | } |
---|
1874 | |
---|
1875 | int |
---|
1876 | vmeTsi148IntEnable(unsigned int level) |
---|
1877 | { |
---|
1878 | return intDoEnDis(level, 1); |
---|
1879 | } |
---|
1880 | |
---|
1881 | int |
---|
1882 | vmeTsi148IntDisable(unsigned int level) |
---|
1883 | { |
---|
1884 | return intDoEnDis(level, -1); |
---|
1885 | } |
---|
1886 | |
---|
1887 | int |
---|
1888 | vmeTsi148IntIsEnabled(unsigned int level) |
---|
1889 | { |
---|
1890 | return intDoEnDis(level, 0); |
---|
1891 | } |
---|
1892 | |
---|
1893 | /* Set IACK width (1,2, or 4 bytes) for a given interrupt level. |
---|
1894 | * |
---|
1895 | * 'width' arg may be 0,1,2 or 4. If zero, the currently active |
---|
1896 | * value is returned but not modified. |
---|
1897 | * |
---|
1898 | * RETURNS: old width or -1 if invalid argument. |
---|
1899 | */ |
---|
1900 | |
---|
1901 | int |
---|
1902 | vmeTsi148SetIackWidth(int level, int width) |
---|
1903 | { |
---|
1904 | int rval; |
---|
1905 | if ( level < 1 || level > 7 || !vmeTsi148IrqMgrInstalled ) |
---|
1906 | return -1; |
---|
1907 | |
---|
1908 | switch ( width ) { |
---|
1909 | default: return -1; |
---|
1910 | case 0: |
---|
1911 | case 1: |
---|
1912 | case 2: |
---|
1913 | case 4: |
---|
1914 | break; |
---|
1915 | } |
---|
1916 | |
---|
1917 | rval = tsi_iack_width[level-1]; |
---|
1918 | if ( width ) |
---|
1919 | tsi_iack_width[level-1] = width; |
---|
1920 | return rval; |
---|
1921 | } |
---|
1922 | |
---|
1923 | int |
---|
1924 | vmeTsi148IntRaiseXX(BERegister *base, int level, unsigned vector) |
---|
1925 | { |
---|
1926 | unsigned long v; |
---|
1927 | |
---|
1928 | CHECK_BASE(base,0,-1); |
---|
1929 | |
---|
1930 | if ( level < 1 || level > 7 || vector > 255 ) |
---|
1931 | return -1; /* invalid argument */ |
---|
1932 | |
---|
1933 | /* Check if already asserted */ |
---|
1934 | if ( (v = TSI_RD(base, TSI_VICR_REG)) & TSI_VICR_IRQS ) { |
---|
1935 | return -2; /* already asserted */ |
---|
1936 | } |
---|
1937 | |
---|
1938 | v &= ~255; |
---|
1939 | |
---|
1940 | v |= TSI_VICR_IRQL(level) | TSI_VICR_STID(vector); |
---|
1941 | |
---|
1942 | /* Write Vector */ |
---|
1943 | TSI_WR(base, TSI_VICR_REG, v); |
---|
1944 | |
---|
1945 | return 0; |
---|
1946 | |
---|
1947 | } |
---|
1948 | |
---|
1949 | int |
---|
1950 | vmeTsi148IntRaise(int level, unsigned vector) |
---|
1951 | { |
---|
1952 | return vmeTsi148IntRaiseXX(THEBASE, level, vector); |
---|
1953 | } |
---|
1954 | |
---|
1955 | /* Loopback test of VME/Tsi148 internal interrupts */ |
---|
1956 | |
---|
1957 | typedef struct { |
---|
1958 | rtems_id q; |
---|
1959 | int l; |
---|
1960 | } LoopbackTstArgs; |
---|
1961 | |
---|
1962 | static void |
---|
1963 | loopbackTstIsr(void *arg, unsigned long vector) |
---|
1964 | { |
---|
1965 | LoopbackTstArgs *pa = arg; |
---|
1966 | if ( RTEMS_SUCCESSFUL != rtems_message_queue_send(pa->q, (void*)&vector, sizeof(vector)) ) { |
---|
1967 | /* Overrun ? */ |
---|
1968 | printk("vmeTsi148IntLoopbackTst: (ISR) message queue full / overrun ? disabling IRQ level %i\n", pa->l); |
---|
1969 | vmeTsi148IntDisable(pa->l); |
---|
1970 | } |
---|
1971 | } |
---|
1972 | |
---|
1973 | int |
---|
1974 | vmeTsi148IntLoopbackTst(int level, unsigned vector) |
---|
1975 | { |
---|
1976 | BERegister *b = THEBASE; |
---|
1977 | rtems_status_code sc; |
---|
1978 | rtems_id q = 0; |
---|
1979 | int installed = 0; |
---|
1980 | int i, err = 0; |
---|
1981 | int doDisable = 0; |
---|
1982 | size_t size; |
---|
1983 | unsigned long msg; |
---|
1984 | char * irqfmt = "VME IRQ @vector %3i %s"; |
---|
1985 | char * iackfmt = "VME IACK %s"; |
---|
1986 | LoopbackTstArgs a; |
---|
1987 | |
---|
1988 | CHECK_BASE(b,0,-1); |
---|
1989 | |
---|
1990 | /* arg check */ |
---|
1991 | if ( level < 1 || level > 7 || vector > 255 ) |
---|
1992 | return -1; |
---|
1993 | |
---|
1994 | /* Create message queue */ |
---|
1995 | if ( RTEMS_SUCCESSFUL != (sc=rtems_message_queue_create( |
---|
1996 | rtems_build_name('t' ,'U','I','I'), |
---|
1997 | 4, |
---|
1998 | sizeof(unsigned long), |
---|
1999 | 0, /* default attributes: fifo, local */ |
---|
2000 | &q)) ) { |
---|
2001 | rtems_error(sc, "vmeTsi148IntLoopbackTst: Unable to create message queue"); |
---|
2002 | goto bail; |
---|
2003 | } |
---|
2004 | |
---|
2005 | a.q = q; |
---|
2006 | a.l = level; |
---|
2007 | |
---|
2008 | /* Install handlers */ |
---|
2009 | if ( vmeTsi148InstallISR(vector, loopbackTstIsr, (void*)&a) ) { |
---|
2010 | uprintf(stderr,"Unable to install VME ISR to vector %i\n",vector); |
---|
2011 | goto bail; |
---|
2012 | } |
---|
2013 | installed++; |
---|
2014 | if ( vmeTsi148InstallISR(TSI_VME_SW_IACK_INT_VEC, loopbackTstIsr, (void*)&a) ) { |
---|
2015 | uprintf(stderr,"Unable to install VME ISR to IACK special vector %i\n",TSI_VME_SW_IACK_INT_VEC); |
---|
2016 | goto bail; |
---|
2017 | } |
---|
2018 | installed++; |
---|
2019 | |
---|
2020 | if ( !vmeTsi148IntIsEnabled(level) && 0==vmeTsi148IntEnable(level) ) |
---|
2021 | doDisable = 1; |
---|
2022 | |
---|
2023 | /* make sure there are no pending interrupts */ |
---|
2024 | TSI_WR(b, TSI_INTC_REG, TSI_INTC_IACKC); |
---|
2025 | |
---|
2026 | if ( vmeTsi148IntEnable( TSI_VME_SW_IACK_INT_VEC ) ) { |
---|
2027 | uprintf(stderr,"Unable to enable IACK interrupt\n"); |
---|
2028 | goto bail; |
---|
2029 | } |
---|
2030 | |
---|
2031 | printf("vmeTsi148 VME interrupt loopback test; STARTING...\n"); |
---|
2032 | printf(" --> asserting VME IRQ level %i\n", level); |
---|
2033 | vmeTsi148IntRaise(level, vector); |
---|
2034 | |
---|
2035 | for ( i = 0; i< 3; i++ ) { |
---|
2036 | sc = rtems_message_queue_receive( |
---|
2037 | q, |
---|
2038 | &msg, |
---|
2039 | &size, |
---|
2040 | RTEMS_WAIT, |
---|
2041 | 20); |
---|
2042 | if ( sc ) { |
---|
2043 | if ( RTEMS_TIMEOUT == sc && i>1 ) { |
---|
2044 | /* OK; we dont' expect more to happen */ |
---|
2045 | sc = 0; |
---|
2046 | } else { |
---|
2047 | rtems_error(sc,"Error waiting for interrupts"); |
---|
2048 | } |
---|
2049 | break; |
---|
2050 | } |
---|
2051 | if ( msg == vector ) { |
---|
2052 | if ( !irqfmt ) { |
---|
2053 | printf("Excess VME IRQ received ?? -- BAD\n"); |
---|
2054 | err = 1; |
---|
2055 | } else { |
---|
2056 | printf(irqfmt, vector, "received -- PASSED\n"); |
---|
2057 | irqfmt = 0; |
---|
2058 | } |
---|
2059 | } else if ( msg == TSI_VME_SW_IACK_INT_VEC ) { |
---|
2060 | if ( !iackfmt ) { |
---|
2061 | printf("Excess VME IACK received ?? -- BAD\n"); |
---|
2062 | err = 1; |
---|
2063 | } else { |
---|
2064 | printf(iackfmt, "received -- PASSED\n"); |
---|
2065 | iackfmt = 0; |
---|
2066 | } |
---|
2067 | } else { |
---|
2068 | printf("Unknown IRQ (vector %lu) received -- BAD\n", msg); |
---|
2069 | err = 1; |
---|
2070 | } |
---|
2071 | } |
---|
2072 | |
---|
2073 | |
---|
2074 | /* Missing anything ? */ |
---|
2075 | if ( irqfmt ) { |
---|
2076 | printf(irqfmt,vector, "MISSED -- BAD\n"); |
---|
2077 | err = 1; |
---|
2078 | } |
---|
2079 | if ( iackfmt ) { |
---|
2080 | printf(iackfmt, "MISSED -- BAD\n"); |
---|
2081 | err = 1; |
---|
2082 | } |
---|
2083 | |
---|
2084 | printf("FINISHED.\n"); |
---|
2085 | |
---|
2086 | bail: |
---|
2087 | if ( doDisable ) |
---|
2088 | vmeTsi148IntDisable(level); |
---|
2089 | vmeTsi148IntDisable( TSI_VME_SW_IACK_INT_VEC ); |
---|
2090 | if ( installed > 0 ) |
---|
2091 | vmeTsi148RemoveISR(vector, loopbackTstIsr, (void*)&a); |
---|
2092 | if ( installed > 1 ) |
---|
2093 | vmeTsi148RemoveISR(TSI_VME_SW_IACK_INT_VEC, loopbackTstIsr, (void*)&a); |
---|
2094 | if ( q ) |
---|
2095 | rtems_message_queue_delete(q); |
---|
2096 | |
---|
2097 | return sc ? sc : err; |
---|
2098 | } |
---|
2099 | |
---|
2100 | unsigned long |
---|
2101 | vmeTsi148ClearVMEBusErrorsXX(BERegister *base, uint32_t *paddr) |
---|
2102 | { |
---|
2103 | unsigned long rval; |
---|
2104 | |
---|
2105 | CHECK_BASE(base,1,-1); |
---|
2106 | |
---|
2107 | rval = TSI_RD(base, TSI_VEAT_REG); |
---|
2108 | if ( rval & TSI_VEAT_VES ) { |
---|
2109 | if ( paddr ) { |
---|
2110 | #if 0 /* no 64-bit support yet */ |
---|
2111 | *paddr = ((unsigned long long)TSI_RD(base, TSI_VEAU_REG))<<32; |
---|
2112 | *paddr |= TSI_RD(base, TSI_VEAL_REG); |
---|
2113 | #else |
---|
2114 | *paddr = TSI_RD(base, TSI_VEAL_REG); |
---|
2115 | #endif |
---|
2116 | } |
---|
2117 | /* clear errors */ |
---|
2118 | TSI_WR(base, TSI_VEAT_REG, TSI_VEAT_VESCL); |
---|
2119 | } else { |
---|
2120 | rval = 0; |
---|
2121 | } |
---|
2122 | return rval; |
---|
2123 | } |
---|
2124 | |
---|
2125 | unsigned long |
---|
2126 | vmeTsi148ClearVMEBusErrors(uint32_t *paddr) |
---|
2127 | { |
---|
2128 | return vmeTsi148ClearVMEBusErrorsXX(THEBASE, paddr); |
---|
2129 | } |
---|
2130 | |
---|
2131 | /** DMA Support **/ |
---|
2132 | |
---|
2133 | /* descriptor must be 8-byte aligned */ |
---|
2134 | typedef struct VmeTsi148DmaListDescriptorRec_ { |
---|
2135 | BEValue dsau, dsal; |
---|
2136 | BEValue ddau, ddal; |
---|
2137 | BEValue dsat, ddat; |
---|
2138 | BEValue dnlau, dnlal; |
---|
2139 | BEValue dcnt, ddbs; |
---|
2140 | } VmeTsi148DmaListDescriptorRec; |
---|
2141 | |
---|
2142 | static void tsi_desc_init (DmaDescriptor); |
---|
2143 | static int tsi_desc_setup (DmaDescriptor, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); |
---|
2144 | static void tsi_desc_setnxt(DmaDescriptor, DmaDescriptor); |
---|
2145 | static void tsi_desc_dump (DmaDescriptor); |
---|
2146 | static int tsi_desc_start (volatile void *controller_addr, int channel, DmaDescriptor p); |
---|
2147 | |
---|
2148 | VMEDmaListClassRec vmeTsi148DmaListClass = { |
---|
2149 | desc_size: sizeof(VmeTsi148DmaListDescriptorRec), |
---|
2150 | desc_align: 8, |
---|
2151 | freeList: 0, |
---|
2152 | desc_alloc: 0, |
---|
2153 | desc_free: 0, |
---|
2154 | desc_init: tsi_desc_init, |
---|
2155 | desc_setnxt:tsi_desc_setnxt, |
---|
2156 | desc_setup: tsi_desc_setup, |
---|
2157 | desc_start: tsi_desc_start, |
---|
2158 | desc_refr: 0, |
---|
2159 | desc_dump: tsi_desc_dump, |
---|
2160 | }; |
---|
2161 | |
---|
2162 | /* DMA Control */ |
---|
2163 | #define TSI_DMA_REG(off,i) ((off)+(((i)&1)<<7)) |
---|
2164 | |
---|
2165 | #define TSI_DCTL_REG(i) TSI_DMA_REG(0x500,i) |
---|
2166 | #define TSI_DCTL0_REG 0x500 |
---|
2167 | #define TSI_DCTL1_REG 0x580 |
---|
2168 | # define TSI_DCTL_ABT (1<<27) /* abort */ |
---|
2169 | # define TSI_DCTL_PAU (1<<26) /* pause */ |
---|
2170 | # define TSI_DCTL_DGO (1<<25) /* GO */ |
---|
2171 | # define TSI_DCTL_MOD (1<<23) /* linked list: 0, direct: 1 */ |
---|
2172 | # define TSI_DCTL_VFAR (1<<17) /* flush FIFO on VME error: 1 (discard: 0) */ |
---|
2173 | # define TSI_DCTL_PFAR (1<<16) /* flush FIFO on PCI error: 1 (discard: 0) */ |
---|
2174 | |
---|
2175 | # define TSI_DCTL_VBKS(i) (((i)&7)<<12) /* VME block size */ |
---|
2176 | # define TSI_DCTL_VBKS_32 TSI_DCTL_VBKS(0) |
---|
2177 | # define TSI_DCTL_VBKS_64 TSI_DCTL_VBKS(1) |
---|
2178 | # define TSI_DCTL_VBKS_128 TSI_DCTL_VBKS(2) |
---|
2179 | # define TSI_DCTL_VBKS_256 TSI_DCTL_VBKS(3) |
---|
2180 | # define TSI_DCTL_VBKS_512 TSI_DCTL_VBKS(4) |
---|
2181 | # define TSI_DCTL_VBKS_1024 TSI_DCTL_VBKS(5) |
---|
2182 | # define TSI_DCTL_VBKS_2048 TSI_DCTL_VBKS(6) |
---|
2183 | # define TSI_DCTL_VBKS_4096 TSI_DCTL_VBKS(7) |
---|
2184 | |
---|
2185 | # define TSI_DCTL_VBOT(i) (((i)&7)<< 8) /* VME back-off time */ |
---|
2186 | # define TSI_DCTL_VBOT_0us TSI_DCTL_VBOT(0) |
---|
2187 | # define TSI_DCTL_VBOT_1us TSI_DCTL_VBOT(1) |
---|
2188 | # define TSI_DCTL_VBOT_2us TSI_DCTL_VBOT(2) |
---|
2189 | # define TSI_DCTL_VBOT_4us TSI_DCTL_VBOT(3) |
---|
2190 | # define TSI_DCTL_VBOT_8us TSI_DCTL_VBOT(4) |
---|
2191 | # define TSI_DCTL_VBOT_16us TSI_DCTL_VBOT(5) |
---|
2192 | # define TSI_DCTL_VBOT_32us TSI_DCTL_VBOT(6) |
---|
2193 | # define TSI_DCTL_VBOT_64us TSI_DCTL_VBOT(7) |
---|
2194 | |
---|
2195 | # define TSI_DCTL_PBKS(i) (((i)&7)<< 4) /* PCI block size */ |
---|
2196 | # define TSI_DCTL_PBKS_32 TSI_DCTL_PBKS(0) |
---|
2197 | # define TSI_DCTL_PBKS_64 TSI_DCTL_PBKS(1) |
---|
2198 | # define TSI_DCTL_PBKS_128 TSI_DCTL_PBKS(2) |
---|
2199 | # define TSI_DCTL_PBKS_256 TSI_DCTL_PBKS(3) |
---|
2200 | # define TSI_DCTL_PBKS_512 TSI_DCTL_PBKS(4) |
---|
2201 | # define TSI_DCTL_PBKS_1024 TSI_DCTL_PBKS(5) |
---|
2202 | # define TSI_DCTL_PBKS_2048 TSI_DCTL_PBKS(6) |
---|
2203 | # define TSI_DCTL_PBKS_4096 TSI_DCTL_PBKS(7) |
---|
2204 | |
---|
2205 | # define TSI_DCTL_PBOT(i) (((i)&7)<< 0) /* PCI back-off time */ |
---|
2206 | # define TSI_DCTL_PBOT_0us TSI_DCTL_PBOT(0) |
---|
2207 | # define TSI_DCTL_PBOT_1us TSI_DCTL_PBOT(1) |
---|
2208 | # define TSI_DCTL_PBOT_2us TSI_DCTL_PBOT(2) |
---|
2209 | # define TSI_DCTL_PBOT_4us TSI_DCTL_PBOT(3) |
---|
2210 | # define TSI_DCTL_PBOT_8us TSI_DCTL_PBOT(4) |
---|
2211 | # define TSI_DCTL_PBOT_16us TSI_DCTL_PBOT(5) |
---|
2212 | # define TSI_DCTL_PBOT_32us TSI_DCTL_PBOT(6) |
---|
2213 | # define TSI_DCTL_PBOT_64us TSI_DCTL_PBOT(7) |
---|
2214 | |
---|
2215 | /* DMA Status */ |
---|
2216 | #define TSI_DSTA_REG(i) TSI_DMA_REG(0x504,i) |
---|
2217 | #define TSI_DSTA0_REG 0x504 |
---|
2218 | #define TSI_DSTA1_REG 0x584 |
---|
2219 | # define TSI_DSTA_ERR (1<<28) |
---|
2220 | # define TSI_DSTA_ABT (1<<27) |
---|
2221 | # define TSI_DSTA_PAU (1<<26) |
---|
2222 | # define TSI_DSTA_DON (1<<25) |
---|
2223 | # define TSI_DSTA_BSY (1<<24) |
---|
2224 | # define TSI_DSTA_ERRS (1<<20) /* Error source; PCI:1, VME:0 */ |
---|
2225 | # define TSI_DSTA_ERT_MSK (3<<16) /* Error type */ |
---|
2226 | # define TSI_DSTA_ERT_BERR_E (0<<16) /* 2eVME even or other bus error */ |
---|
2227 | # define TSI_DSTA_ERT_BERR_O (1<<16) /* 2eVME odd bus error */ |
---|
2228 | # define TSI_DSTA_ERT_SLVE_E (2<<16) /* 2eVME even or other slave termination */ |
---|
2229 | # define TSI_DSTA_ERT_SLVE_O (3<<16) /* 2eVME odd slave termination; 2eSST read last word invalid */ |
---|
2230 | |
---|
2231 | /* DMA Current source address upper */ |
---|
2232 | #define TSI_DCSAU_REG(i) TSI_DMA_REG(0x508,i) |
---|
2233 | #define TSI_DCSAU0_REG 0x508 |
---|
2234 | #define TSI_DCSAU1_REG 0x588 |
---|
2235 | |
---|
2236 | /* DMA Current source address lower */ |
---|
2237 | #define TSI_DCSAL_REG(i) TSI_DMA_REG(0x50c,i) |
---|
2238 | #define TSI_DCSAL0_REG 0x50c |
---|
2239 | #define TSI_DCSAL1_REG 0x58c |
---|
2240 | |
---|
2241 | /* DMA Current destination address upper */ |
---|
2242 | #define TSI_DCDAU_REG(i) TSI_DMA_REG(0x510,i) |
---|
2243 | #define TSI_DCDAU0_REG 0x510 |
---|
2244 | #define TSI_DCDAU1_REG 0x590 |
---|
2245 | |
---|
2246 | /* DMA Current destination address lower */ |
---|
2247 | #define TSI_DCDAL_REG(i) TSI_DMA_REG(0x514,i) |
---|
2248 | #define TSI_DCDAL0_REG 0x514 |
---|
2249 | #define TSI_DCDAL1_REG 0x594 |
---|
2250 | |
---|
2251 | /* DMA Current link address upper */ |
---|
2252 | #define TSI_DCLAU_REG(i) TSI_DMA_REG(0x518,i) |
---|
2253 | #define TSI_DCLAU0_REG 0x518 |
---|
2254 | #define TSI_DCLAU1_REG 0x598 |
---|
2255 | |
---|
2256 | /* DMA Current link address lower */ |
---|
2257 | #define TSI_DCLAL_REG(i) TSI_DMA_REG(0x51c,i) |
---|
2258 | #define TSI_DCLAL0_REG 0x51c |
---|
2259 | #define TSI_DCLAL1_REG 0x59c |
---|
2260 | |
---|
2261 | /* DMA Source address upper */ |
---|
2262 | #define TSI_DSAU_REG(i) TSI_DMA_REG(0x520,i) |
---|
2263 | #define TSI_DSAU0_REG 0x520 |
---|
2264 | #define TSI_DSAU1_REG 0x5a0 |
---|
2265 | |
---|
2266 | /* DMA Source address lower */ |
---|
2267 | #define TSI_DSAL_REG(i) TSI_DMA_REG(0x524,i) |
---|
2268 | #define TSI_DSAL0_REG 0x524 |
---|
2269 | #define TSI_DSAL1_REG 0x5a4 |
---|
2270 | |
---|
2271 | /* DMA Destination address upper */ |
---|
2272 | #define TSI_DDAU_REG(i) TSI_DMA_REG(0x528,i) |
---|
2273 | #define TSI_DDAU0_REG 0x528 |
---|
2274 | #define TSI_DDAU1_REG 0x5a8 |
---|
2275 | |
---|
2276 | /* DMA Destination address lower */ |
---|
2277 | #define TSI_DDAL_REG(i) TSI_DMA_REG(0x52c,i) |
---|
2278 | #define TSI_DDAL0_REG 0x52c |
---|
2279 | #define TSI_DDAL1_REG 0x5ac |
---|
2280 | |
---|
2281 | /* DMA Source Attribute */ |
---|
2282 | #define TSI_DSAT_REG(i) TSI_DMA_REG(0x530,i) |
---|
2283 | #define TSI_DSAT0_REG 0x530 |
---|
2284 | #define TSI_DSAT1_REG 0x5b0 |
---|
2285 | |
---|
2286 | /* DMA Destination Attribute */ |
---|
2287 | #define TSI_DDAT_REG(i) TSI_DMA_REG(0x534,i) |
---|
2288 | #define TSI_DDAT0_REG 0x534 |
---|
2289 | #define TSI_DDAT1_REG 0x5b4 |
---|
2290 | |
---|
2291 | # define TSI_DXAT_TYP(i) (((i)&3)<<28) /* Xfer type */ |
---|
2292 | # define TSI_DXAT_TYP_PCI TSI_DXAT_TYP(0) |
---|
2293 | # define TSI_DXAT_TYP_VME TSI_DXAT_TYP(1) |
---|
2294 | # define TSI_DSAT_TYP_PAT TSI_DXAT_TYP(2) /* pattern */ |
---|
2295 | |
---|
2296 | # define TSI_DSAT_PSZ (1<<25) /* pattern size 32-bit: 0, 8-bit: 1 */ |
---|
2297 | # define TSI_DSAT_NIN (1<<24) /* no-increment */ |
---|
2298 | |
---|
2299 | # define TSI_DXAT_OTAT_MSK ((1<<13)-1) /* get bits compatible with OTAT */ |
---|
2300 | |
---|
2301 | # define TSI_DXAT_SSTM(i) (((i)&3)<<11) /* 2eSST Xfer rate (MB/s) */ |
---|
2302 | # define TSI_DXAT_SSTM_116 TSI_DXAT_SSTM(0) |
---|
2303 | # define TSI_DXAT_SSTM_267 TSI_DXAT_SSTM(1) |
---|
2304 | # define TSI_DXAT_SSTM_320 TSI_DXAT_SSTM(2) |
---|
2305 | |
---|
2306 | # define TSI_DXAT_TM(i) (((i)&7)<< 8) /* VME Xfer mode */ |
---|
2307 | # define TSI_DXAT_TM_SCT TSI_DXAT_TM(0) |
---|
2308 | # define TSI_DXAT_TM_BLT TSI_DXAT_TM(1) |
---|
2309 | # define TSI_DXAT_TM_MBLT TSI_DXAT_TM(2) |
---|
2310 | # define TSI_DXAT_TM_2eVME TSI_DXAT_TM(3) |
---|
2311 | # define TSI_DXAT_TM_2eSST TSI_DXAT_TM(4) |
---|
2312 | # define TSI_DSAT_TM_2eSST_B TSI_DXAT_TM(5) /* 2eSST broadcast */ |
---|
2313 | |
---|
2314 | # define TSI_DXAT_DBW(i) (((i)&3)<< 6) /* VME Data width */ |
---|
2315 | # define TSI_DXAT_DBW_16 TSI_DXAT_DBW(0) |
---|
2316 | # define TSI_DXAT_DBW_32 TSI_DXAT_DBW(1) |
---|
2317 | |
---|
2318 | # define TSI_DXAT_SUP (1<<5) /* supervisor access */ |
---|
2319 | # define TSI_DXAT_PGM (1<<4) /* program access */ |
---|
2320 | |
---|
2321 | # define TSI_DXAT_AM(i) (((i)&15)<<0) /* VME Address mode */ |
---|
2322 | # define TSI_DXAT_AM_A16 TSI_DXAT_AM(0) |
---|
2323 | # define TSI_DXAT_AM_A24 TSI_DXAT_AM(1) |
---|
2324 | # define TSI_DXAT_AM_A32 TSI_DXAT_AM(2) |
---|
2325 | # define TSI_DXAT_AM_A64 TSI_DXAT_AM(4) |
---|
2326 | # define TSI_DXAT_AM_CSR TSI_DXAT_AM(5) |
---|
2327 | |
---|
2328 | /* DMA Next link address upper */ |
---|
2329 | #define TSI_DNLAU_REG(i) TSI_DMA_REG(0x538,i) |
---|
2330 | #define TSI_DNLAU0_REG 0x538 |
---|
2331 | #define TSI_DNLAU1_REG 0x5b8 |
---|
2332 | |
---|
2333 | /* DMA Next link address lower */ |
---|
2334 | #define TSI_DNLAL_REG(i) TSI_DMA_REG(0x53c,i) |
---|
2335 | #define TSI_DNLAL0_REG 0x53c |
---|
2336 | #define TSI_DNLAL1_REG 0x5bc |
---|
2337 | |
---|
2338 | # define TSI_DNLAL_LLA 1 /* last element in chain */ |
---|
2339 | |
---|
2340 | /* DMA Byte Count */ |
---|
2341 | #define TSI_DCNT_REG(i) TSI_DMA_REG(0x540,i) |
---|
2342 | #define TSI_DCNT0_REG 0x540 |
---|
2343 | #define TSI_DCNT1_REG 0x54c |
---|
2344 | |
---|
2345 | /* DMA 2eSST destination broadcast select */ |
---|
2346 | #define TSI_DDBS_REG(i) TSI_DMA_REG(0x544,i) |
---|
2347 | #define TSI_DDBS0_REG 0x544 |
---|
2348 | #define TSI_DDBS1_REG 0x5c4 |
---|
2349 | |
---|
2350 | /* Convert canonical xfer_mode into Tsi148 bits; return -1 if invalid */ |
---|
2351 | static uint32_t |
---|
2352 | vme_attr(uint32_t xfer_mode) |
---|
2353 | { |
---|
2354 | uint32_t vme_mode; |
---|
2355 | if ( am2omode(xfer_mode, &vme_mode) ) |
---|
2356 | return BSP_VMEDMA_STATUS_UNSUP; |
---|
2357 | |
---|
2358 | /* am2omode may set prefetch and other bits */ |
---|
2359 | vme_mode &= TSI_DXAT_OTAT_MSK; |
---|
2360 | vme_mode |= TSI_DXAT_TYP_VME; |
---|
2361 | |
---|
2362 | if ( BSP_VMEDMA_MODE_NOINC_VME & xfer_mode ) { |
---|
2363 | /* no-incr. only supported on source address */ |
---|
2364 | if ( (BSP_VMEDMA_MODE_PCI2VME & xfer_mode) ) |
---|
2365 | return BSP_VMEDMA_STATUS_UNSUP; |
---|
2366 | vme_mode |= TSI_DSAT_NIN; |
---|
2367 | } |
---|
2368 | |
---|
2369 | return vme_mode; |
---|
2370 | } |
---|
2371 | |
---|
2372 | static uint32_t |
---|
2373 | pci_attr(uint32_t xfer_mode) |
---|
2374 | { |
---|
2375 | uint32_t pci_mode = 0; |
---|
2376 | if ( BSP_VMEDMA_MODE_NOINC_PCI & xfer_mode ) { |
---|
2377 | /* no-incr. only supported on source address */ |
---|
2378 | if ( ! (BSP_VMEDMA_MODE_PCI2VME & xfer_mode) ) |
---|
2379 | return BSP_VMEDMA_STATUS_UNSUP; |
---|
2380 | pci_mode |= TSI_DSAT_NIN; |
---|
2381 | } |
---|
2382 | return pci_mode; |
---|
2383 | } |
---|
2384 | |
---|
2385 | static void tsi_desc_init(DmaDescriptor p) |
---|
2386 | { |
---|
2387 | VmeTsi148DmaListDescriptor d = p; |
---|
2388 | st_be32( &d->dnlau, 0 ); |
---|
2389 | st_be32( &d->dnlal, TSI_DNLAL_LLA ); |
---|
2390 | st_be32( &d->ddbs, (1<<22)-1 ); /* SSTB broadcast not yet fully supported */ |
---|
2391 | } |
---|
2392 | |
---|
2393 | static void |
---|
2394 | tsi_desc_setnxt(DmaDescriptor p, DmaDescriptor n) |
---|
2395 | { |
---|
2396 | VmeTsi148DmaListDescriptor d = p; |
---|
2397 | if ( 0 == n ) { |
---|
2398 | st_be32( &d->dnlal, TSI_DNLAL_LLA ); |
---|
2399 | } else { |
---|
2400 | st_be32( &d->dnlal, BSP_LOCAL2PCI_ADDR((uint32_t)n) ); |
---|
2401 | } |
---|
2402 | } |
---|
2403 | |
---|
2404 | static void |
---|
2405 | tsi_desc_dump(DmaDescriptor p) |
---|
2406 | { |
---|
2407 | VmeTsi148DmaListDescriptor d = p; |
---|
2408 | printf(" DSA: 0x%08lx%08lx\n", ld_be32(&d->dsau), ld_be32(&d->dsal)); |
---|
2409 | printf(" DDA: 0x%08lx%08lx\n", ld_be32(&d->ddau), ld_be32(&d->ddal)); |
---|
2410 | printf(" NLA: 0x%08lx%08lx\n", ld_be32(&d->dnlau), ld_be32(&d->dnlal)); |
---|
2411 | printf(" SAT: 0x%08lx DAT: 0x%08lx\n", ld_be32(&d->dsat), ld_be32(&d->ddat)); |
---|
2412 | printf(" CNT: 0x%08lx\n", ld_be32(&d->dcnt)); |
---|
2413 | } |
---|
2414 | |
---|
2415 | |
---|
2416 | int |
---|
2417 | vmeTsi148DmaSetupXX(BERegister *base, int channel, uint32_t mode, uint32_t xfer_mode, void *custom) |
---|
2418 | { |
---|
2419 | uint32_t ctl = 0; |
---|
2420 | uint32_t vmeatt, pciatt, sat, dat; |
---|
2421 | |
---|
2422 | if ( channel < 0 || channel > 1 ) |
---|
2423 | return BSP_VMEDMA_STATUS_UNSUP; |
---|
2424 | |
---|
2425 | /* Check bus mode */ |
---|
2426 | if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == (vmeatt = vme_attr(xfer_mode)) ) |
---|
2427 | return -2; |
---|
2428 | |
---|
2429 | /* Check PCI bus mode */ |
---|
2430 | if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == (pciatt = pci_attr(xfer_mode)) ) |
---|
2431 | return -3; |
---|
2432 | |
---|
2433 | /* Compute control word; bottleneck is VME; */ |
---|
2434 | ctl |= TSI_DCTL_PBKS_32; |
---|
2435 | ctl |= (BSP_VMEDMA_OPT_THROUGHPUT == mode ? TSI_DCTL_PBOT_0us : TSI_DCTL_PBOT_1us); |
---|
2436 | |
---|
2437 | switch ( mode ) { |
---|
2438 | case BSP_VMEDMA_OPT_THROUGHPUT: |
---|
2439 | ctl |= TSI_DCTL_VBKS_1024; |
---|
2440 | ctl |= TSI_DCTL_VBOT_0us; |
---|
2441 | break; |
---|
2442 | |
---|
2443 | case BSP_VMEDMA_OPT_LOWLATENCY: |
---|
2444 | ctl |= TSI_DCTL_VBKS_32; |
---|
2445 | ctl |= TSI_DCTL_VBOT_0us; |
---|
2446 | break; |
---|
2447 | |
---|
2448 | case BSP_VMEDMA_OPT_SHAREDBUS: |
---|
2449 | ctl |= TSI_DCTL_VBKS_128; |
---|
2450 | ctl |= TSI_DCTL_VBOT_64us; |
---|
2451 | break; |
---|
2452 | |
---|
2453 | case BSP_VMEDMA_OPT_CUSTOM: |
---|
2454 | ctl = *(uint32_t*)custom; |
---|
2455 | break; |
---|
2456 | |
---|
2457 | default: |
---|
2458 | case BSP_VMEDMA_OPT_DEFAULT: |
---|
2459 | ctl = 0; |
---|
2460 | break; |
---|
2461 | } |
---|
2462 | TSI_WR(base, TSI_DCTL_REG(channel), ctl); |
---|
2463 | if ( BSP_VMEDMA_MODE_PCI2VME & xfer_mode ) { |
---|
2464 | dat = vmeatt; sat = pciatt; |
---|
2465 | } else { |
---|
2466 | sat = vmeatt; dat = pciatt; |
---|
2467 | } |
---|
2468 | TSI_WR(base, TSI_DSAT_REG(channel), sat); |
---|
2469 | TSI_WR(base, TSI_DDAT_REG(channel), dat); |
---|
2470 | return 0; |
---|
2471 | } |
---|
2472 | |
---|
2473 | int |
---|
2474 | vmeTsi148DmaSetup(int channel, uint32_t mode, uint32_t xfer_mode, void *custom) |
---|
2475 | { |
---|
2476 | BERegister *base = THEBASE; |
---|
2477 | return vmeTsi148DmaSetupXX(base, channel, mode, xfer_mode, custom); |
---|
2478 | } |
---|
2479 | |
---|
2480 | |
---|
2481 | int |
---|
2482 | vmeTsi148DmaListStartXX(BERegister *base, int channel, VmeTsi148DmaListDescriptor d) |
---|
2483 | { |
---|
2484 | uint32_t ctl; |
---|
2485 | |
---|
2486 | if ( d ) { |
---|
2487 | /* Set list pointer and start */ |
---|
2488 | if ( channel < 0 || channel > 1 ) |
---|
2489 | return BSP_VMEDMA_STATUS_UNSUP; |
---|
2490 | |
---|
2491 | if ( TSI_DSTA_BSY & TSI_RD(base, TSI_DSTA_REG(channel)) ) |
---|
2492 | return BSP_VMEDMA_STATUS_BUSY; /* channel busy */ |
---|
2493 | |
---|
2494 | TSI_WR(base, TSI_DNLAL_REG(channel), (uint32_t)BSP_LOCAL2PCI_ADDR(d)); |
---|
2495 | |
---|
2496 | asm volatile("":::"memory"); |
---|
2497 | |
---|
2498 | /* Start transfer */ |
---|
2499 | ctl = TSI_RD(base, TSI_DCTL_REG(channel)) | TSI_DCTL_DGO; |
---|
2500 | ctl &= ~TSI_DCTL_MOD; |
---|
2501 | TSI_WR(base, TSI_DCTL_REG(channel), ctl); |
---|
2502 | } |
---|
2503 | /* else: list vs. direct mode is set by the respective start commands */ |
---|
2504 | return 0; |
---|
2505 | } |
---|
2506 | |
---|
2507 | int |
---|
2508 | vmeTsi148DmaListStart(int channel, VmeTsi148DmaListDescriptor d) |
---|
2509 | { |
---|
2510 | BERegister *base = THEBASE; |
---|
2511 | return vmeTsi148DmaListStartXX(base, channel, d); |
---|
2512 | } |
---|
2513 | |
---|
2514 | int |
---|
2515 | vmeTsi148DmaStartXX(BERegister *base, int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes) |
---|
2516 | { |
---|
2517 | uint32_t src, dst, ctl; |
---|
2518 | |
---|
2519 | if ( channel < 0 || channel > 1 ) |
---|
2520 | return BSP_VMEDMA_STATUS_UNSUP; |
---|
2521 | |
---|
2522 | if ( TSI_DSTA_BSY & TSI_RD(base, TSI_DSTA_REG(channel)) ) |
---|
2523 | return BSP_VMEDMA_STATUS_BUSY; /* channel busy */ |
---|
2524 | |
---|
2525 | /* retrieve direction from dst attribute */ |
---|
2526 | if ( TSI_DXAT_TYP_VME & TSI_RD(base, TSI_DDAT_REG(channel)) ) { |
---|
2527 | dst = vme_addr; |
---|
2528 | src = pci_addr; |
---|
2529 | } else { |
---|
2530 | src = vme_addr; |
---|
2531 | dst = pci_addr; |
---|
2532 | } |
---|
2533 | /* FIXME: we leave the 'upper' registers (topmost 32bits) alone. |
---|
2534 | * Probably, we should reset them at init... |
---|
2535 | */ |
---|
2536 | TSI_WR(base, TSI_DSAL_REG(channel), src); |
---|
2537 | TSI_WR(base, TSI_DDAL_REG(channel), dst); |
---|
2538 | TSI_WR(base, TSI_DCNT_REG(channel), n_bytes); |
---|
2539 | |
---|
2540 | asm volatile("":::"memory"); |
---|
2541 | |
---|
2542 | /* Start transfer */ |
---|
2543 | ctl = TSI_RD(base, TSI_DCTL_REG(channel)) | TSI_DCTL_DGO | TSI_DCTL_MOD; |
---|
2544 | TSI_WR(base, TSI_DCTL_REG(channel), ctl); |
---|
2545 | |
---|
2546 | return 0; |
---|
2547 | } |
---|
2548 | |
---|
2549 | int |
---|
2550 | vmeTsi148DmaStart(int channel, uint32_t pci_addr, uint32_t vme_addr, uint32_t n_bytes) |
---|
2551 | { |
---|
2552 | BERegister *base = THEBASE; |
---|
2553 | return vmeTsi148DmaStartXX(base, channel, pci_addr, vme_addr, n_bytes); |
---|
2554 | } |
---|
2555 | |
---|
2556 | uint32_t |
---|
2557 | vmeTsi148DmaStatusXX(BERegister *base, int channel) |
---|
2558 | { |
---|
2559 | uint32_t st = TSI_RD(base, TSI_DSTA_REG(channel)); |
---|
2560 | |
---|
2561 | if ( channel < 0 || channel > 1 ) |
---|
2562 | return BSP_VMEDMA_STATUS_UNSUP; |
---|
2563 | |
---|
2564 | st = TSI_RD(base, TSI_DSTA_REG(channel)); |
---|
2565 | |
---|
2566 | /* Status can be zero if an empty list (all counts == 0) is executed */ |
---|
2567 | if ( (TSI_DSTA_DON & st) || 0 == st ) |
---|
2568 | return BSP_VMEDMA_STATUS_OK; |
---|
2569 | |
---|
2570 | if ( TSI_DSTA_BSY & st ) |
---|
2571 | return BSP_VMEDMA_STATUS_BUSY; /* channel busy */ |
---|
2572 | |
---|
2573 | if ( TSI_DSTA_ERR & st ) { |
---|
2574 | if ( TSI_DSTA_ERRS & st ) |
---|
2575 | return BSP_VMEDMA_STATUS_BERR_PCI; |
---|
2576 | if ( ! (TSI_DSTA_ERT_SLVE_E & st) ) |
---|
2577 | return BSP_VMEDMA_STATUS_BERR_VME; |
---|
2578 | } |
---|
2579 | |
---|
2580 | return BSP_VMEDMA_STATUS_OERR; |
---|
2581 | } |
---|
2582 | |
---|
2583 | uint32_t |
---|
2584 | vmeTsi148DmaStatus(int channel) |
---|
2585 | { |
---|
2586 | BERegister *base = THEBASE; |
---|
2587 | return vmeTsi148DmaStatusXX(base, channel); |
---|
2588 | } |
---|
2589 | |
---|
2590 | #define ALL_BITS_NEEDED (BSP_VMEDMA_MSK_ATTR | BSP_VMEDMA_MSK_PCIA | BSP_VMEDMA_MSK_VMEA) |
---|
2591 | |
---|
2592 | static int |
---|
2593 | tsi_desc_setup ( |
---|
2594 | DmaDescriptor p, |
---|
2595 | uint32_t attr_mask, |
---|
2596 | uint32_t xfer_mode, |
---|
2597 | uint32_t pci_addr, |
---|
2598 | uint32_t vme_addr, |
---|
2599 | uint32_t n_bytes) |
---|
2600 | { |
---|
2601 | VmeTsi148DmaListDescriptor d = p; |
---|
2602 | uint32_t vmeatt = 0, pciatt = 0, tmp, src, dst, dat, sat; |
---|
2603 | |
---|
2604 | /* argument check */ |
---|
2605 | |
---|
2606 | /* since we must vme/pci into src/dst we need the direction |
---|
2607 | * bit. Reject requests that have only part of the mask |
---|
2608 | * bits set. It would be possible to be more sophisticated |
---|
2609 | * by caching more information but we try to be simple here... |
---|
2610 | */ |
---|
2611 | tmp = attr_mask & ALL_BITS_NEEDED; |
---|
2612 | if ( tmp != 0 && tmp != ALL_BITS_NEEDED ) |
---|
2613 | return -1; |
---|
2614 | |
---|
2615 | if ( BSP_VMEDMA_MSK_ATTR & attr_mask ) { |
---|
2616 | /* Check VME bus mode */ |
---|
2617 | vmeatt = vme_attr(xfer_mode); |
---|
2618 | if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == vmeatt ) |
---|
2619 | return -1; |
---|
2620 | |
---|
2621 | /* Check PCI bus mode */ |
---|
2622 | pciatt = pci_attr(xfer_mode); |
---|
2623 | if ( (uint32_t)BSP_VMEDMA_STATUS_UNSUP == pciatt ) |
---|
2624 | return -1; |
---|
2625 | } |
---|
2626 | |
---|
2627 | if ( BSP_VMEDMA_MSK_ATTR & attr_mask ) { |
---|
2628 | if ( BSP_VMEDMA_MODE_PCI2VME & xfer_mode ) { |
---|
2629 | dat = vmeatt; sat = pciatt; |
---|
2630 | dst = vme_addr; src = pci_addr; |
---|
2631 | } else { |
---|
2632 | sat = vmeatt; dat = pciatt; |
---|
2633 | src = vme_addr; dst = pci_addr; |
---|
2634 | } |
---|
2635 | st_be32( &d->dsau, 0 ); st_be32( &d->dsal, src ); |
---|
2636 | st_be32( &d->ddau, 0 ); st_be32( &d->ddal, dst ); |
---|
2637 | st_be32( &d->dsat, sat ); st_be32( &d->ddat, dat ); |
---|
2638 | } |
---|
2639 | |
---|
2640 | if ( BSP_VMEDMA_MSK_BCNT & attr_mask ) |
---|
2641 | st_be32( &d->dcnt, n_bytes); |
---|
2642 | |
---|
2643 | return 0; |
---|
2644 | } |
---|
2645 | |
---|
2646 | static int |
---|
2647 | tsi_desc_start (volatile void *controller_addr, int channel, DmaDescriptor p) |
---|
2648 | { |
---|
2649 | VmeTsi148DmaListDescriptor d = p; |
---|
2650 | if ( !controller_addr ) |
---|
2651 | controller_addr = THEBASE; |
---|
2652 | return vmeTsi148DmaListStartXX((BERegister*)controller_addr, channel, d); |
---|
2653 | } |
---|
2654 | |
---|
2655 | #ifdef DEBUG_MODULAR |
---|
2656 | void |
---|
2657 | _cexpModuleInitialize(void* unused) |
---|
2658 | { |
---|
2659 | vmeTsi148Init(); |
---|
2660 | vmeTsi148Reset(); |
---|
2661 | } |
---|
2662 | |
---|
2663 | int |
---|
2664 | _cexpModuleFinalize(void *unused) |
---|
2665 | { |
---|
2666 | int i; |
---|
2667 | int rval = 1; |
---|
2668 | void (*isrs[TSI_NUM_WIRES])() = { |
---|
2669 | isr_pin0, |
---|
2670 | isr_pin1, |
---|
2671 | isr_pin2, |
---|
2672 | isr_pin3, |
---|
2673 | }; |
---|
2674 | |
---|
2675 | rtems_irq_connect_data xx; |
---|
2676 | xx.on = my_no_op; /* at _least_ they could check for a 0 pointer */ |
---|
2677 | xx.off = my_no_op; |
---|
2678 | xx.isOn = my_isOn; |
---|
2679 | |
---|
2680 | TSI_WR(THEBASE, TSI_INTEO_REG, 0); |
---|
2681 | |
---|
2682 | for ( i=0; i<TSI_NUM_INT_VECS; i++) { |
---|
2683 | /* Dont even bother to uninstall handlers */ |
---|
2684 | } |
---|
2685 | if ( vmeTsi148IrqMgrInstalled ) { |
---|
2686 | for ( i=0; i<TSI_NUM_WIRES; i++ ) { |
---|
2687 | if ( (int)(xx.name = devs[0].pic_pin[i]) >=0 ) { |
---|
2688 | xx.hdl = isrs[i]; |
---|
2689 | rval = rval && BSP_remove_rtems_irq_handler(&xx); |
---|
2690 | } |
---|
2691 | } |
---|
2692 | } |
---|
2693 | return !rval; |
---|
2694 | } |
---|
2695 | #endif |
---|