diff options
Diffstat (limited to 'drivers/isdn/hardware/eicon/os_4bri.c')
-rw-r--r-- | drivers/isdn/hardware/eicon/os_4bri.c | 1131 |
1 files changed, 1131 insertions, 0 deletions
diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c new file mode 100644 index 000000000000..cccfabc1117d --- /dev/null +++ b/drivers/isdn/hardware/eicon/os_4bri.c | |||
@@ -0,0 +1,1131 @@ | |||
1 | /* $Id: os_4bri.c,v 1.28.4.4 2005/02/11 19:40:25 armin Exp $ */ | ||
2 | |||
3 | #include "platform.h" | ||
4 | #include "debuglib.h" | ||
5 | #include "cardtype.h" | ||
6 | #include "pc.h" | ||
7 | #include "pr_pc.h" | ||
8 | #include "di_defs.h" | ||
9 | #include "dsp_defs.h" | ||
10 | #include "di.h" | ||
11 | #include "io.h" | ||
12 | |||
13 | #include "xdi_msg.h" | ||
14 | #include "xdi_adapter.h" | ||
15 | #include "os_4bri.h" | ||
16 | #include "diva_pci.h" | ||
17 | #include "mi_pc.h" | ||
18 | #include "dsrv4bri.h" | ||
19 | |||
20 | static void *diva_xdiLoadFileFile = NULL; | ||
21 | static dword diva_xdiLoadFileLength = 0; | ||
22 | |||
23 | /* | ||
24 | ** IMPORTS | ||
25 | */ | ||
26 | extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter); | ||
27 | extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter); | ||
28 | extern void diva_xdi_display_adapter_features(int card); | ||
29 | extern void diva_add_slave_adapter(diva_os_xdi_adapter_t * a); | ||
30 | |||
31 | extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter); | ||
32 | extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter); | ||
33 | |||
34 | extern int diva_card_read_xlog(diva_os_xdi_adapter_t * a); | ||
35 | |||
36 | /* | ||
37 | ** LOCALS | ||
38 | */ | ||
39 | static unsigned long _4bri_bar_length[4] = { | ||
40 | 0x100, | ||
41 | 0x100, /* I/O */ | ||
42 | MQ_MEMORY_SIZE, | ||
43 | 0x2000 | ||
44 | }; | ||
45 | static unsigned long _4bri_v2_bar_length[4] = { | ||
46 | 0x100, | ||
47 | 0x100, /* I/O */ | ||
48 | MQ2_MEMORY_SIZE, | ||
49 | 0x10000 | ||
50 | }; | ||
51 | static unsigned long _4bri_v2_bri_bar_length[4] = { | ||
52 | 0x100, | ||
53 | 0x100, /* I/O */ | ||
54 | BRI2_MEMORY_SIZE, | ||
55 | 0x10000 | ||
56 | }; | ||
57 | |||
58 | |||
59 | static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a); | ||
60 | static int _4bri_get_serial_number(diva_os_xdi_adapter_t * a); | ||
61 | static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, | ||
62 | diva_xdi_um_cfg_cmd_t * cmd, | ||
63 | int length); | ||
64 | static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t * a); | ||
65 | static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t * a, | ||
66 | byte * data, dword length); | ||
67 | static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter); | ||
68 | static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter, | ||
69 | dword address, | ||
70 | const byte * data, | ||
71 | dword length, dword limit); | ||
72 | static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter, | ||
73 | dword start_address, dword features); | ||
74 | static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter); | ||
75 | static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t * a); | ||
76 | |||
77 | static int _4bri_is_rev_2_card(int card_ordinal) | ||
78 | { | ||
79 | switch (card_ordinal) { | ||
80 | case CARDTYPE_DIVASRV_Q_8M_V2_PCI: | ||
81 | case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI: | ||
82 | case CARDTYPE_DIVASRV_B_2M_V2_PCI: | ||
83 | case CARDTYPE_DIVASRV_B_2F_PCI: | ||
84 | case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI: | ||
85 | return (1); | ||
86 | } | ||
87 | return (0); | ||
88 | } | ||
89 | |||
90 | static int _4bri_is_rev_2_bri_card(int card_ordinal) | ||
91 | { | ||
92 | switch (card_ordinal) { | ||
93 | case CARDTYPE_DIVASRV_B_2M_V2_PCI: | ||
94 | case CARDTYPE_DIVASRV_B_2F_PCI: | ||
95 | case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI: | ||
96 | return (1); | ||
97 | } | ||
98 | return (0); | ||
99 | } | ||
100 | |||
101 | static void diva_4bri_set_addresses(diva_os_xdi_adapter_t *a) | ||
102 | { | ||
103 | dword offset = a->resources.pci.qoffset; | ||
104 | dword c_offset = offset * a->xdi_adapter.ControllerNumber; | ||
105 | |||
106 | a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 2; | ||
107 | a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2; | ||
108 | a->resources.pci.mem_type_id[MEM_TYPE_CONTROL] = 2; | ||
109 | a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 0; | ||
110 | a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 3; | ||
111 | a->resources.pci.mem_type_id[MEM_TYPE_PROM] = 0; | ||
112 | |||
113 | /* | ||
114 | Set up hardware related pointers | ||
115 | */ | ||
116 | a->xdi_adapter.Address = a->resources.pci.addr[2]; /* BAR2 SDRAM */ | ||
117 | a->xdi_adapter.Address += c_offset; | ||
118 | |||
119 | a->xdi_adapter.Control = a->resources.pci.addr[2]; /* BAR2 SDRAM */ | ||
120 | |||
121 | a->xdi_adapter.ram = a->resources.pci.addr[2]; /* BAR2 SDRAM */ | ||
122 | a->xdi_adapter.ram += c_offset + (offset - MQ_SHARED_RAM_SIZE); | ||
123 | |||
124 | a->xdi_adapter.reset = a->resources.pci.addr[0]; /* BAR0 CONFIG */ | ||
125 | /* | ||
126 | ctlReg contains the register address for the MIPS CPU reset control | ||
127 | */ | ||
128 | a->xdi_adapter.ctlReg = a->resources.pci.addr[3]; /* BAR3 CNTRL */ | ||
129 | /* | ||
130 | prom contains the register address for FPGA and EEPROM programming | ||
131 | */ | ||
132 | a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E]; | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | ** BAR0 - MEM - 0x100 - CONFIG MEM | ||
137 | ** BAR1 - I/O - 0x100 - UNUSED | ||
138 | ** BAR2 - MEM - MQ_MEMORY_SIZE (MQ2_MEMORY_SIZE on Rev.2) - SDRAM | ||
139 | ** BAR3 - MEM - 0x2000 (0x10000 on Rev.2) - CNTRL | ||
140 | ** | ||
141 | ** Called by master adapter, that will initialize and add slave adapters | ||
142 | */ | ||
143 | int diva_4bri_init_card(diva_os_xdi_adapter_t * a) | ||
144 | { | ||
145 | int bar, i; | ||
146 | byte __iomem *p; | ||
147 | PADAPTER_LIST_ENTRY quadro_list; | ||
148 | diva_os_xdi_adapter_t *diva_current; | ||
149 | diva_os_xdi_adapter_t *adapter_list[4]; | ||
150 | PISDN_ADAPTER Slave; | ||
151 | unsigned long bar_length[sizeof(_4bri_bar_length) / | ||
152 | sizeof(_4bri_bar_length[0])]; | ||
153 | int v2 = _4bri_is_rev_2_card(a->CardOrdinal); | ||
154 | int tasks = _4bri_is_rev_2_bri_card(a->CardOrdinal) ? 1 : MQ_INSTANCE_COUNT; | ||
155 | int factor = (tasks == 1) ? 1 : 2; | ||
156 | |||
157 | if (v2) { | ||
158 | if (_4bri_is_rev_2_bri_card(a->CardOrdinal)) { | ||
159 | memcpy(bar_length, _4bri_v2_bri_bar_length, | ||
160 | sizeof(bar_length)); | ||
161 | } else { | ||
162 | memcpy(bar_length, _4bri_v2_bar_length, | ||
163 | sizeof(bar_length)); | ||
164 | } | ||
165 | } else { | ||
166 | memcpy(bar_length, _4bri_bar_length, sizeof(bar_length)); | ||
167 | } | ||
168 | DBG_TRC(("SDRAM_LENGTH=%08x, tasks=%d, factor=%d", | ||
169 | bar_length[2], tasks, factor)) | ||
170 | |||
171 | /* | ||
172 | Get Serial Number | ||
173 | The serial number of 4BRI is accessible in accordance with PCI spec | ||
174 | via command register located in configuration space, also we do not | ||
175 | have to map any BAR before we can access it | ||
176 | */ | ||
177 | if (!_4bri_get_serial_number(a)) { | ||
178 | DBG_ERR(("A: 4BRI can't get Serial Number")) | ||
179 | diva_4bri_cleanup_adapter(a); | ||
180 | return (-1); | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | Set properties | ||
185 | */ | ||
186 | a->xdi_adapter.Properties = CardProperties[a->CardOrdinal]; | ||
187 | DBG_LOG(("Load %s, SN:%ld, bus:%02x, func:%02x", | ||
188 | a->xdi_adapter.Properties.Name, | ||
189 | a->xdi_adapter.serialNo, | ||
190 | a->resources.pci.bus, a->resources.pci.func)) | ||
191 | |||
192 | /* | ||
193 | First initialization step: get and check hardware resoures. | ||
194 | Do not map resources and do not access card at this step | ||
195 | */ | ||
196 | for (bar = 0; bar < 4; bar++) { | ||
197 | a->resources.pci.bar[bar] = | ||
198 | divasa_get_pci_bar(a->resources.pci.bus, | ||
199 | a->resources.pci.func, bar, | ||
200 | a->resources.pci.hdev); | ||
201 | if (!a->resources.pci.bar[bar] | ||
202 | || (a->resources.pci.bar[bar] == 0xFFFFFFF0)) { | ||
203 | DBG_ERR( | ||
204 | ("A: invalid bar[%d]=%08x", bar, | ||
205 | a->resources.pci.bar[bar])) | ||
206 | return (-1); | ||
207 | } | ||
208 | } | ||
209 | a->resources.pci.irq = | ||
210 | (byte) divasa_get_pci_irq(a->resources.pci.bus, | ||
211 | a->resources.pci.func, | ||
212 | a->resources.pci.hdev); | ||
213 | if (!a->resources.pci.irq) { | ||
214 | DBG_ERR(("A: invalid irq")); | ||
215 | return (-1); | ||
216 | } | ||
217 | |||
218 | a->xdi_adapter.sdram_bar = a->resources.pci.bar[2]; | ||
219 | |||
220 | /* | ||
221 | Map all MEMORY BAR's | ||
222 | */ | ||
223 | for (bar = 0; bar < 4; bar++) { | ||
224 | if (bar != 1) { /* ignore I/O */ | ||
225 | a->resources.pci.addr[bar] = | ||
226 | divasa_remap_pci_bar(a, bar, a->resources.pci.bar[bar], | ||
227 | bar_length[bar]); | ||
228 | if (!a->resources.pci.addr[bar]) { | ||
229 | DBG_ERR(("A: 4BRI: can't map bar[%d]", bar)) | ||
230 | diva_4bri_cleanup_adapter(a); | ||
231 | return (-1); | ||
232 | } | ||
233 | } | ||
234 | } | ||
235 | |||
236 | /* | ||
237 | Register I/O port | ||
238 | */ | ||
239 | sprintf(&a->port_name[0], "DIVA 4BRI %ld", (long) a->xdi_adapter.serialNo); | ||
240 | |||
241 | if (diva_os_register_io_port(a, 1, a->resources.pci.bar[1], | ||
242 | bar_length[1], &a->port_name[0], 1)) { | ||
243 | DBG_ERR(("A: 4BRI: can't register bar[1]")) | ||
244 | diva_4bri_cleanup_adapter(a); | ||
245 | return (-1); | ||
246 | } | ||
247 | |||
248 | a->resources.pci.addr[1] = | ||
249 | (void *) (unsigned long) a->resources.pci.bar[1]; | ||
250 | |||
251 | /* | ||
252 | Set cleanup pointer for base adapter only, so slave adapter | ||
253 | will be unable to get cleanup | ||
254 | */ | ||
255 | a->interface.cleanup_adapter_proc = diva_4bri_cleanup_adapter; | ||
256 | |||
257 | /* | ||
258 | Create slave adapters | ||
259 | */ | ||
260 | if (tasks > 1) { | ||
261 | if (!(a->slave_adapters[0] = | ||
262 | (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a)))) | ||
263 | { | ||
264 | diva_4bri_cleanup_adapter(a); | ||
265 | return (-1); | ||
266 | } | ||
267 | if (!(a->slave_adapters[1] = | ||
268 | (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a)))) | ||
269 | { | ||
270 | diva_os_free(0, a->slave_adapters[0]); | ||
271 | a->slave_adapters[0] = NULL; | ||
272 | diva_4bri_cleanup_adapter(a); | ||
273 | return (-1); | ||
274 | } | ||
275 | if (!(a->slave_adapters[2] = | ||
276 | (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a)))) | ||
277 | { | ||
278 | diva_os_free(0, a->slave_adapters[0]); | ||
279 | diva_os_free(0, a->slave_adapters[1]); | ||
280 | a->slave_adapters[0] = NULL; | ||
281 | a->slave_adapters[1] = NULL; | ||
282 | diva_4bri_cleanup_adapter(a); | ||
283 | return (-1); | ||
284 | } | ||
285 | memset(a->slave_adapters[0], 0x00, sizeof(*a)); | ||
286 | memset(a->slave_adapters[1], 0x00, sizeof(*a)); | ||
287 | memset(a->slave_adapters[2], 0x00, sizeof(*a)); | ||
288 | } | ||
289 | |||
290 | adapter_list[0] = a; | ||
291 | adapter_list[1] = a->slave_adapters[0]; | ||
292 | adapter_list[2] = a->slave_adapters[1]; | ||
293 | adapter_list[3] = a->slave_adapters[2]; | ||
294 | |||
295 | /* | ||
296 | Allocate slave list | ||
297 | */ | ||
298 | quadro_list = | ||
299 | (PADAPTER_LIST_ENTRY) diva_os_malloc(0, sizeof(*quadro_list)); | ||
300 | if (!(a->slave_list = quadro_list)) { | ||
301 | for (i = 0; i < (tasks - 1); i++) { | ||
302 | diva_os_free(0, a->slave_adapters[i]); | ||
303 | a->slave_adapters[i] = NULL; | ||
304 | } | ||
305 | diva_4bri_cleanup_adapter(a); | ||
306 | return (-1); | ||
307 | } | ||
308 | memset(quadro_list, 0x00, sizeof(*quadro_list)); | ||
309 | |||
310 | /* | ||
311 | Set interfaces | ||
312 | */ | ||
313 | a->xdi_adapter.QuadroList = quadro_list; | ||
314 | for (i = 0; i < tasks; i++) { | ||
315 | adapter_list[i]->xdi_adapter.ControllerNumber = i; | ||
316 | adapter_list[i]->xdi_adapter.tasks = tasks; | ||
317 | quadro_list->QuadroAdapter[i] = | ||
318 | &adapter_list[i]->xdi_adapter; | ||
319 | } | ||
320 | |||
321 | for (i = 0; i < tasks; i++) { | ||
322 | diva_current = adapter_list[i]; | ||
323 | |||
324 | diva_current->dsp_mask = 0x00000003; | ||
325 | |||
326 | diva_current->xdi_adapter.a.io = | ||
327 | &diva_current->xdi_adapter; | ||
328 | diva_current->xdi_adapter.DIRequest = request; | ||
329 | diva_current->interface.cmd_proc = diva_4bri_cmd_card_proc; | ||
330 | diva_current->xdi_adapter.Properties = | ||
331 | CardProperties[a->CardOrdinal]; | ||
332 | diva_current->CardOrdinal = a->CardOrdinal; | ||
333 | |||
334 | diva_current->xdi_adapter.Channels = | ||
335 | CardProperties[a->CardOrdinal].Channels; | ||
336 | diva_current->xdi_adapter.e_max = | ||
337 | CardProperties[a->CardOrdinal].E_info; | ||
338 | diva_current->xdi_adapter.e_tbl = | ||
339 | diva_os_malloc(0, | ||
340 | diva_current->xdi_adapter.e_max * | ||
341 | sizeof(E_INFO)); | ||
342 | |||
343 | if (!diva_current->xdi_adapter.e_tbl) { | ||
344 | diva_4bri_cleanup_slave_adapters(a); | ||
345 | diva_4bri_cleanup_adapter(a); | ||
346 | for (i = 1; i < (tasks - 1); i++) { | ||
347 | diva_os_free(0, adapter_list[i]); | ||
348 | } | ||
349 | return (-1); | ||
350 | } | ||
351 | memset(diva_current->xdi_adapter.e_tbl, 0x00, | ||
352 | diva_current->xdi_adapter.e_max * sizeof(E_INFO)); | ||
353 | |||
354 | if (diva_os_initialize_spin_lock(&diva_current->xdi_adapter.isr_spin_lock, "isr")) { | ||
355 | diva_4bri_cleanup_slave_adapters(a); | ||
356 | diva_4bri_cleanup_adapter(a); | ||
357 | for (i = 1; i < (tasks - 1); i++) { | ||
358 | diva_os_free(0, adapter_list[i]); | ||
359 | } | ||
360 | return (-1); | ||
361 | } | ||
362 | if (diva_os_initialize_spin_lock(&diva_current->xdi_adapter.data_spin_lock, "data")) { | ||
363 | diva_4bri_cleanup_slave_adapters(a); | ||
364 | diva_4bri_cleanup_adapter(a); | ||
365 | for (i = 1; i < (tasks - 1); i++) { | ||
366 | diva_os_free(0, adapter_list[i]); | ||
367 | } | ||
368 | return (-1); | ||
369 | } | ||
370 | |||
371 | strcpy(diva_current->xdi_adapter.req_soft_isr. dpc_thread_name, "kdivas4brid"); | ||
372 | |||
373 | if (diva_os_initialize_soft_isr (&diva_current->xdi_adapter.req_soft_isr, DIDpcRoutine, | ||
374 | &diva_current->xdi_adapter)) { | ||
375 | diva_4bri_cleanup_slave_adapters(a); | ||
376 | diva_4bri_cleanup_adapter(a); | ||
377 | for (i = 1; i < (tasks - 1); i++) { | ||
378 | diva_os_free(0, adapter_list[i]); | ||
379 | } | ||
380 | return (-1); | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | Do not initialize second DPC - only one thread will be created | ||
385 | */ | ||
386 | diva_current->xdi_adapter.isr_soft_isr.object = | ||
387 | diva_current->xdi_adapter.req_soft_isr.object; | ||
388 | } | ||
389 | |||
390 | if (v2) { | ||
391 | prepare_qBri2_functions(&a->xdi_adapter); | ||
392 | } else { | ||
393 | prepare_qBri_functions(&a->xdi_adapter); | ||
394 | } | ||
395 | |||
396 | for (i = 0; i < tasks; i++) { | ||
397 | diva_current = adapter_list[i]; | ||
398 | if (i) | ||
399 | memcpy(&diva_current->resources, &a->resources, sizeof(divas_card_resources_t)); | ||
400 | diva_current->resources.pci.qoffset = (a->xdi_adapter.MemorySize >> factor); | ||
401 | } | ||
402 | |||
403 | /* | ||
404 | Set up hardware related pointers | ||
405 | */ | ||
406 | a->xdi_adapter.cfg = (void *) (unsigned long) a->resources.pci.bar[0]; /* BAR0 CONFIG */ | ||
407 | a->xdi_adapter.port = (void *) (unsigned long) a->resources.pci.bar[1]; /* BAR1 */ | ||
408 | a->xdi_adapter.ctlReg = (void *) (unsigned long) a->resources.pci.bar[3]; /* BAR3 CNTRL */ | ||
409 | |||
410 | for (i = 0; i < tasks; i++) { | ||
411 | diva_current = adapter_list[i]; | ||
412 | diva_4bri_set_addresses(diva_current); | ||
413 | Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i]; | ||
414 | Slave->MultiMaster = &a->xdi_adapter; | ||
415 | Slave->sdram_bar = a->xdi_adapter.sdram_bar; | ||
416 | if (i) { | ||
417 | Slave->serialNo = ((dword) (Slave->ControllerNumber << 24)) | | ||
418 | a->xdi_adapter.serialNo; | ||
419 | Slave->cardType = a->xdi_adapter.cardType; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | /* | ||
424 | reset contains the base address for the PLX 9054 register set | ||
425 | */ | ||
426 | p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter); | ||
427 | WRITE_BYTE(&p[PLX9054_INTCSR], 0x00); /* disable PCI interrupts */ | ||
428 | DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p); | ||
429 | |||
430 | /* | ||
431 | Set IRQ handler | ||
432 | */ | ||
433 | a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq; | ||
434 | sprintf(a->xdi_adapter.irq_info.irq_name, "DIVA 4BRI %ld", | ||
435 | (long) a->xdi_adapter.serialNo); | ||
436 | |||
437 | if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr, | ||
438 | a->xdi_adapter.irq_info.irq_name)) { | ||
439 | diva_4bri_cleanup_slave_adapters(a); | ||
440 | diva_4bri_cleanup_adapter(a); | ||
441 | for (i = 1; i < (tasks - 1); i++) { | ||
442 | diva_os_free(0, adapter_list[i]); | ||
443 | } | ||
444 | return (-1); | ||
445 | } | ||
446 | |||
447 | a->xdi_adapter.irq_info.registered = 1; | ||
448 | |||
449 | /* | ||
450 | Add three slave adapters | ||
451 | */ | ||
452 | if (tasks > 1) { | ||
453 | diva_add_slave_adapter(adapter_list[1]); | ||
454 | diva_add_slave_adapter(adapter_list[2]); | ||
455 | diva_add_slave_adapter(adapter_list[3]); | ||
456 | } | ||
457 | |||
458 | diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name, | ||
459 | a->resources.pci.irq, a->xdi_adapter.serialNo); | ||
460 | |||
461 | return (0); | ||
462 | } | ||
463 | |||
464 | /* | ||
465 | ** Cleanup function will be called for master adapter only | ||
466 | ** this is garanteed by design: cleanup callback is set | ||
467 | ** by master adapter only | ||
468 | */ | ||
469 | static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a) | ||
470 | { | ||
471 | int bar; | ||
472 | |||
473 | /* | ||
474 | Stop adapter if running | ||
475 | */ | ||
476 | if (a->xdi_adapter.Initialized) { | ||
477 | diva_4bri_stop_adapter(a); | ||
478 | } | ||
479 | |||
480 | /* | ||
481 | Remove IRQ handler | ||
482 | */ | ||
483 | if (a->xdi_adapter.irq_info.registered) { | ||
484 | diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr); | ||
485 | } | ||
486 | a->xdi_adapter.irq_info.registered = 0; | ||
487 | |||
488 | /* | ||
489 | Free DPC's and spin locks on all adapters | ||
490 | */ | ||
491 | diva_4bri_cleanup_slave_adapters(a); | ||
492 | |||
493 | /* | ||
494 | Unmap all BARS | ||
495 | */ | ||
496 | for (bar = 0; bar < 4; bar++) { | ||
497 | if (bar != 1) { | ||
498 | if (a->resources.pci.bar[bar] | ||
499 | && a->resources.pci.addr[bar]) { | ||
500 | divasa_unmap_pci_bar(a->resources.pci.addr[bar]); | ||
501 | a->resources.pci.bar[bar] = 0; | ||
502 | a->resources.pci.addr[bar] = NULL; | ||
503 | } | ||
504 | } | ||
505 | } | ||
506 | |||
507 | /* | ||
508 | Unregister I/O | ||
509 | */ | ||
510 | if (a->resources.pci.bar[1] && a->resources.pci.addr[1]) { | ||
511 | diva_os_register_io_port(a, 0, a->resources.pci.bar[1], | ||
512 | _4bri_is_rev_2_card(a-> | ||
513 | CardOrdinal) ? | ||
514 | _4bri_v2_bar_length[1] : | ||
515 | _4bri_bar_length[1], | ||
516 | &a->port_name[0], 1); | ||
517 | a->resources.pci.bar[1] = 0; | ||
518 | a->resources.pci.addr[1] = NULL; | ||
519 | } | ||
520 | |||
521 | if (a->slave_list) { | ||
522 | diva_os_free(0, a->slave_list); | ||
523 | a->slave_list = NULL; | ||
524 | } | ||
525 | |||
526 | return (0); | ||
527 | } | ||
528 | |||
529 | static int _4bri_get_serial_number(diva_os_xdi_adapter_t * a) | ||
530 | { | ||
531 | dword data[64]; | ||
532 | dword serNo; | ||
533 | word addr, status, i, j; | ||
534 | byte Bus, Slot; | ||
535 | void *hdev; | ||
536 | |||
537 | Bus = a->resources.pci.bus; | ||
538 | Slot = a->resources.pci.func; | ||
539 | hdev = a->resources.pci.hdev; | ||
540 | |||
541 | for (i = 0; i < 64; ++i) { | ||
542 | addr = i * 4; | ||
543 | for (j = 0; j < 5; ++j) { | ||
544 | PCIwrite(Bus, Slot, 0x4E, &addr, sizeof(addr), | ||
545 | hdev); | ||
546 | diva_os_wait(1); | ||
547 | PCIread(Bus, Slot, 0x4E, &status, sizeof(status), | ||
548 | hdev); | ||
549 | if (status & 0x8000) | ||
550 | break; | ||
551 | } | ||
552 | if (j >= 5) { | ||
553 | DBG_ERR(("EEPROM[%d] read failed (0x%x)", i * 4, addr)) | ||
554 | return (0); | ||
555 | } | ||
556 | PCIread(Bus, Slot, 0x50, &data[i], sizeof(data[i]), hdev); | ||
557 | } | ||
558 | DBG_BLK(((char *) &data[0], sizeof(data))) | ||
559 | |||
560 | serNo = data[32]; | ||
561 | if (serNo == 0 || serNo == 0xffffffff) | ||
562 | serNo = data[63]; | ||
563 | |||
564 | if (!serNo) { | ||
565 | DBG_LOG(("W: Serial Number == 0, create one serial number")); | ||
566 | serNo = a->resources.pci.bar[1] & 0xffff0000; | ||
567 | serNo |= a->resources.pci.bus << 8; | ||
568 | serNo |= a->resources.pci.func; | ||
569 | } | ||
570 | |||
571 | a->xdi_adapter.serialNo = serNo; | ||
572 | |||
573 | DBG_REG(("Serial No. : %ld", a->xdi_adapter.serialNo)) | ||
574 | |||
575 | return (serNo); | ||
576 | } | ||
577 | |||
578 | /* | ||
579 | ** Release resources of slave adapters | ||
580 | */ | ||
581 | static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t * a) | ||
582 | { | ||
583 | diva_os_xdi_adapter_t *adapter_list[4]; | ||
584 | diva_os_xdi_adapter_t *diva_current; | ||
585 | int i; | ||
586 | |||
587 | adapter_list[0] = a; | ||
588 | adapter_list[1] = a->slave_adapters[0]; | ||
589 | adapter_list[2] = a->slave_adapters[1]; | ||
590 | adapter_list[3] = a->slave_adapters[2]; | ||
591 | |||
592 | for (i = 0; i < a->xdi_adapter.tasks; i++) { | ||
593 | diva_current = adapter_list[i]; | ||
594 | if (diva_current) { | ||
595 | diva_os_destroy_spin_lock(&diva_current-> | ||
596 | xdi_adapter. | ||
597 | isr_spin_lock, "unload"); | ||
598 | diva_os_destroy_spin_lock(&diva_current-> | ||
599 | xdi_adapter. | ||
600 | data_spin_lock, | ||
601 | "unload"); | ||
602 | |||
603 | diva_os_cancel_soft_isr(&diva_current->xdi_adapter. | ||
604 | req_soft_isr); | ||
605 | diva_os_cancel_soft_isr(&diva_current->xdi_adapter. | ||
606 | isr_soft_isr); | ||
607 | |||
608 | diva_os_remove_soft_isr(&diva_current->xdi_adapter. | ||
609 | req_soft_isr); | ||
610 | diva_current->xdi_adapter.isr_soft_isr.object = NULL; | ||
611 | |||
612 | if (diva_current->xdi_adapter.e_tbl) { | ||
613 | diva_os_free(0, | ||
614 | diva_current->xdi_adapter. | ||
615 | e_tbl); | ||
616 | } | ||
617 | diva_current->xdi_adapter.e_tbl = NULL; | ||
618 | diva_current->xdi_adapter.e_max = 0; | ||
619 | diva_current->xdi_adapter.e_count = 0; | ||
620 | } | ||
621 | } | ||
622 | |||
623 | return (0); | ||
624 | } | ||
625 | |||
626 | static int | ||
627 | diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, | ||
628 | diva_xdi_um_cfg_cmd_t * cmd, int length) | ||
629 | { | ||
630 | int ret = -1; | ||
631 | |||
632 | if (cmd->adapter != a->controller) { | ||
633 | DBG_ERR(("A: 4bri_cmd, invalid controller=%d != %d", | ||
634 | cmd->adapter, a->controller)) | ||
635 | return (-1); | ||
636 | } | ||
637 | |||
638 | switch (cmd->command) { | ||
639 | case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL: | ||
640 | a->xdi_mbox.data_length = sizeof(dword); | ||
641 | a->xdi_mbox.data = | ||
642 | diva_os_malloc(0, a->xdi_mbox.data_length); | ||
643 | if (a->xdi_mbox.data) { | ||
644 | *(dword *) a->xdi_mbox.data = | ||
645 | (dword) a->CardOrdinal; | ||
646 | a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; | ||
647 | ret = 0; | ||
648 | } | ||
649 | break; | ||
650 | |||
651 | case DIVA_XDI_UM_CMD_GET_SERIAL_NR: | ||
652 | a->xdi_mbox.data_length = sizeof(dword); | ||
653 | a->xdi_mbox.data = | ||
654 | diva_os_malloc(0, a->xdi_mbox.data_length); | ||
655 | if (a->xdi_mbox.data) { | ||
656 | *(dword *) a->xdi_mbox.data = | ||
657 | (dword) a->xdi_adapter.serialNo; | ||
658 | a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; | ||
659 | ret = 0; | ||
660 | } | ||
661 | break; | ||
662 | |||
663 | case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG: | ||
664 | if (!a->xdi_adapter.ControllerNumber) { | ||
665 | /* | ||
666 | Only master adapter can access hardware config | ||
667 | */ | ||
668 | a->xdi_mbox.data_length = sizeof(dword) * 9; | ||
669 | a->xdi_mbox.data = | ||
670 | diva_os_malloc(0, a->xdi_mbox.data_length); | ||
671 | if (a->xdi_mbox.data) { | ||
672 | int i; | ||
673 | dword *data = (dword *) a->xdi_mbox.data; | ||
674 | |||
675 | for (i = 0; i < 8; i++) { | ||
676 | *data++ = a->resources.pci.bar[i]; | ||
677 | } | ||
678 | *data++ = (dword) a->resources.pci.irq; | ||
679 | a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; | ||
680 | ret = 0; | ||
681 | } | ||
682 | } | ||
683 | break; | ||
684 | |||
685 | case DIVA_XDI_UM_CMD_GET_CARD_STATE: | ||
686 | if (!a->xdi_adapter.ControllerNumber) { | ||
687 | a->xdi_mbox.data_length = sizeof(dword); | ||
688 | a->xdi_mbox.data = | ||
689 | diva_os_malloc(0, a->xdi_mbox.data_length); | ||
690 | if (a->xdi_mbox.data) { | ||
691 | dword *data = (dword *) a->xdi_mbox.data; | ||
692 | if (!a->xdi_adapter.ram | ||
693 | || !a->xdi_adapter.reset | ||
694 | || !a->xdi_adapter.cfg) { | ||
695 | *data = 3; | ||
696 | } else if (a->xdi_adapter.trapped) { | ||
697 | *data = 2; | ||
698 | } else if (a->xdi_adapter.Initialized) { | ||
699 | *data = 1; | ||
700 | } else { | ||
701 | *data = 0; | ||
702 | } | ||
703 | a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; | ||
704 | ret = 0; | ||
705 | } | ||
706 | } | ||
707 | break; | ||
708 | |||
709 | case DIVA_XDI_UM_CMD_WRITE_FPGA: | ||
710 | if (!a->xdi_adapter.ControllerNumber) { | ||
711 | ret = | ||
712 | diva_4bri_write_fpga_image(a, | ||
713 | (byte *) & cmd[1], | ||
714 | cmd->command_data. | ||
715 | write_fpga. | ||
716 | image_length); | ||
717 | } | ||
718 | break; | ||
719 | |||
720 | case DIVA_XDI_UM_CMD_RESET_ADAPTER: | ||
721 | if (!a->xdi_adapter.ControllerNumber) { | ||
722 | ret = diva_4bri_reset_adapter(&a->xdi_adapter); | ||
723 | } | ||
724 | break; | ||
725 | |||
726 | case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK: | ||
727 | if (!a->xdi_adapter.ControllerNumber) { | ||
728 | ret = diva_4bri_write_sdram_block(&a->xdi_adapter, | ||
729 | cmd-> | ||
730 | command_data. | ||
731 | write_sdram. | ||
732 | offset, | ||
733 | (byte *) & | ||
734 | cmd[1], | ||
735 | cmd-> | ||
736 | command_data. | ||
737 | write_sdram. | ||
738 | length, | ||
739 | a->xdi_adapter. | ||
740 | MemorySize); | ||
741 | } | ||
742 | break; | ||
743 | |||
744 | case DIVA_XDI_UM_CMD_START_ADAPTER: | ||
745 | if (!a->xdi_adapter.ControllerNumber) { | ||
746 | ret = diva_4bri_start_adapter(&a->xdi_adapter, | ||
747 | cmd->command_data. | ||
748 | start.offset, | ||
749 | cmd->command_data. | ||
750 | start.features); | ||
751 | } | ||
752 | break; | ||
753 | |||
754 | case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES: | ||
755 | if (!a->xdi_adapter.ControllerNumber) { | ||
756 | a->xdi_adapter.features = | ||
757 | cmd->command_data.features.features; | ||
758 | a->xdi_adapter.a.protocol_capabilities = | ||
759 | a->xdi_adapter.features; | ||
760 | DBG_TRC(("Set raw protocol features (%08x)", | ||
761 | a->xdi_adapter.features)) | ||
762 | ret = 0; | ||
763 | } | ||
764 | break; | ||
765 | |||
766 | case DIVA_XDI_UM_CMD_STOP_ADAPTER: | ||
767 | if (!a->xdi_adapter.ControllerNumber) { | ||
768 | ret = diva_4bri_stop_adapter(a); | ||
769 | } | ||
770 | break; | ||
771 | |||
772 | case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY: | ||
773 | ret = diva_card_read_xlog(a); | ||
774 | break; | ||
775 | |||
776 | case DIVA_XDI_UM_CMD_READ_SDRAM: | ||
777 | if (!a->xdi_adapter.ControllerNumber | ||
778 | && a->xdi_adapter.Address) { | ||
779 | if ( | ||
780 | (a->xdi_mbox.data_length = | ||
781 | cmd->command_data.read_sdram.length)) { | ||
782 | if ( | ||
783 | (a->xdi_mbox.data_length + | ||
784 | cmd->command_data.read_sdram.offset) < | ||
785 | a->xdi_adapter.MemorySize) { | ||
786 | a->xdi_mbox.data = | ||
787 | diva_os_malloc(0, | ||
788 | a->xdi_mbox. | ||
789 | data_length); | ||
790 | if (a->xdi_mbox.data) { | ||
791 | byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter); | ||
792 | byte __iomem *src = p; | ||
793 | byte *dst = a->xdi_mbox.data; | ||
794 | dword len = a->xdi_mbox.data_length; | ||
795 | |||
796 | src += cmd->command_data.read_sdram.offset; | ||
797 | |||
798 | while (len--) { | ||
799 | *dst++ = READ_BYTE(src++); | ||
800 | } | ||
801 | DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p); | ||
802 | a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; | ||
803 | ret = 0; | ||
804 | } | ||
805 | } | ||
806 | } | ||
807 | } | ||
808 | break; | ||
809 | |||
810 | default: | ||
811 | DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller, | ||
812 | cmd->command)) | ||
813 | } | ||
814 | |||
815 | return (ret); | ||
816 | } | ||
817 | |||
818 | void *xdiLoadFile(char *FileName, unsigned long *FileLength, | ||
819 | unsigned long lim) | ||
820 | { | ||
821 | void *ret = diva_xdiLoadFileFile; | ||
822 | |||
823 | if (FileLength) { | ||
824 | *FileLength = diva_xdiLoadFileLength; | ||
825 | } | ||
826 | diva_xdiLoadFileFile = NULL; | ||
827 | diva_xdiLoadFileLength = 0; | ||
828 | |||
829 | return (ret); | ||
830 | } | ||
831 | |||
832 | void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter) | ||
833 | { | ||
834 | } | ||
835 | |||
836 | void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter) | ||
837 | { | ||
838 | } | ||
839 | |||
840 | static int | ||
841 | diva_4bri_write_fpga_image(diva_os_xdi_adapter_t * a, byte * data, | ||
842 | dword length) | ||
843 | { | ||
844 | int ret; | ||
845 | |||
846 | diva_xdiLoadFileFile = data; | ||
847 | diva_xdiLoadFileLength = length; | ||
848 | |||
849 | ret = qBri_FPGA_download(&a->xdi_adapter); | ||
850 | |||
851 | diva_xdiLoadFileFile = NULL; | ||
852 | diva_xdiLoadFileLength = 0; | ||
853 | |||
854 | return (ret ? 0 : -1); | ||
855 | } | ||
856 | |||
857 | static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter) | ||
858 | { | ||
859 | PISDN_ADAPTER Slave; | ||
860 | int i; | ||
861 | |||
862 | if (!IoAdapter->Address || !IoAdapter->reset) { | ||
863 | return (-1); | ||
864 | } | ||
865 | if (IoAdapter->Initialized) { | ||
866 | DBG_ERR(("A: A(%d) can't reset 4BRI adapter - please stop first", | ||
867 | IoAdapter->ANum)) | ||
868 | return (-1); | ||
869 | } | ||
870 | |||
871 | /* | ||
872 | Forget all entities on all adapters | ||
873 | */ | ||
874 | for (i = 0; ((i < IoAdapter->tasks) && IoAdapter->QuadroList); i++) { | ||
875 | Slave = IoAdapter->QuadroList->QuadroAdapter[i]; | ||
876 | Slave->e_count = 0; | ||
877 | if (Slave->e_tbl) { | ||
878 | memset(Slave->e_tbl, 0x00, | ||
879 | Slave->e_max * sizeof(E_INFO)); | ||
880 | } | ||
881 | Slave->head = 0; | ||
882 | Slave->tail = 0; | ||
883 | Slave->assign = 0; | ||
884 | Slave->trapped = 0; | ||
885 | |||
886 | memset(&Slave->a.IdTable[0], 0x00, | ||
887 | sizeof(Slave->a.IdTable)); | ||
888 | memset(&Slave->a.IdTypeTable[0], 0x00, | ||
889 | sizeof(Slave->a.IdTypeTable)); | ||
890 | memset(&Slave->a.FlowControlIdTable[0], 0x00, | ||
891 | sizeof(Slave->a.FlowControlIdTable)); | ||
892 | memset(&Slave->a.FlowControlSkipTable[0], 0x00, | ||
893 | sizeof(Slave->a.FlowControlSkipTable)); | ||
894 | memset(&Slave->a.misc_flags_table[0], 0x00, | ||
895 | sizeof(Slave->a.misc_flags_table)); | ||
896 | memset(&Slave->a.rx_stream[0], 0x00, | ||
897 | sizeof(Slave->a.rx_stream)); | ||
898 | memset(&Slave->a.tx_stream[0], 0x00, | ||
899 | sizeof(Slave->a.tx_stream)); | ||
900 | memset(&Slave->a.tx_pos[0], 0x00, sizeof(Slave->a.tx_pos)); | ||
901 | memset(&Slave->a.rx_pos[0], 0x00, sizeof(Slave->a.rx_pos)); | ||
902 | } | ||
903 | |||
904 | return (0); | ||
905 | } | ||
906 | |||
907 | |||
908 | static int | ||
909 | diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter, | ||
910 | dword address, | ||
911 | const byte * data, dword length, dword limit) | ||
912 | { | ||
913 | byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); | ||
914 | byte __iomem *mem = p; | ||
915 | |||
916 | if (((address + length) >= limit) || !mem) { | ||
917 | DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p); | ||
918 | DBG_ERR(("A: A(%d) write 4BRI address=0x%08lx", | ||
919 | IoAdapter->ANum, address + length)) | ||
920 | return (-1); | ||
921 | } | ||
922 | mem += address; | ||
923 | |||
924 | while (length--) { | ||
925 | WRITE_BYTE(mem++, *data++); | ||
926 | } | ||
927 | |||
928 | DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p); | ||
929 | return (0); | ||
930 | } | ||
931 | |||
932 | static int | ||
933 | diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter, | ||
934 | dword start_address, dword features) | ||
935 | { | ||
936 | volatile word __iomem *signature; | ||
937 | int started = 0; | ||
938 | int i; | ||
939 | byte __iomem *p; | ||
940 | |||
941 | /* | ||
942 | start adapter | ||
943 | */ | ||
944 | start_qBri_hardware(IoAdapter); | ||
945 | |||
946 | p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter); | ||
947 | /* | ||
948 | wait for signature in shared memory (max. 3 seconds) | ||
949 | */ | ||
950 | signature = (volatile word __iomem *) (&p[0x1E]); | ||
951 | |||
952 | for (i = 0; i < 300; ++i) { | ||
953 | diva_os_wait(10); | ||
954 | if (READ_WORD(&signature[0]) == 0x4447) { | ||
955 | DBG_TRC(("Protocol startup time %d.%02d seconds", | ||
956 | (i / 100), (i % 100))) | ||
957 | started = 1; | ||
958 | break; | ||
959 | } | ||
960 | } | ||
961 | |||
962 | for (i = 1; i < IoAdapter->tasks; i++) { | ||
963 | IoAdapter->QuadroList->QuadroAdapter[i]->features = | ||
964 | IoAdapter->features; | ||
965 | IoAdapter->QuadroList->QuadroAdapter[i]->a. | ||
966 | protocol_capabilities = IoAdapter->features; | ||
967 | } | ||
968 | |||
969 | if (!started) { | ||
970 | DBG_FTL(("%s: Adapter selftest failed, signature=%04x", | ||
971 | IoAdapter->Properties.Name, | ||
972 | READ_WORD(&signature[0]))) | ||
973 | DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); | ||
974 | (*(IoAdapter->trapFnc)) (IoAdapter); | ||
975 | IoAdapter->stop(IoAdapter); | ||
976 | return (-1); | ||
977 | } | ||
978 | DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); | ||
979 | |||
980 | for (i = 0; i < IoAdapter->tasks; i++) { | ||
981 | IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 1; | ||
982 | IoAdapter->QuadroList->QuadroAdapter[i]->IrqCount = 0; | ||
983 | } | ||
984 | |||
985 | if (check_qBri_interrupt(IoAdapter)) { | ||
986 | DBG_ERR(("A: A(%d) interrupt test failed", | ||
987 | IoAdapter->ANum)) | ||
988 | for (i = 0; i < IoAdapter->tasks; i++) { | ||
989 | IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0; | ||
990 | } | ||
991 | IoAdapter->stop(IoAdapter); | ||
992 | return (-1); | ||
993 | } | ||
994 | |||
995 | IoAdapter->Properties.Features = (word) features; | ||
996 | diva_xdi_display_adapter_features(IoAdapter->ANum); | ||
997 | |||
998 | for (i = 0; i < IoAdapter->tasks; i++) { | ||
999 | DBG_LOG(("A(%d) %s adapter successfull started", | ||
1000 | IoAdapter->QuadroList->QuadroAdapter[i]->ANum, | ||
1001 | (IoAdapter->tasks == 1) ? "BRI 2.0" : "4BRI")) | ||
1002 | diva_xdi_didd_register_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum); | ||
1003 | IoAdapter->QuadroList->QuadroAdapter[i]->Properties.Features = (word) features; | ||
1004 | } | ||
1005 | |||
1006 | return (0); | ||
1007 | } | ||
1008 | |||
1009 | static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter) | ||
1010 | { | ||
1011 | #ifdef SUPPORT_INTERRUPT_TEST_ON_4BRI | ||
1012 | int i; | ||
1013 | ADAPTER *a = &IoAdapter->a; | ||
1014 | byte __iomem *p; | ||
1015 | |||
1016 | IoAdapter->IrqCount = 0; | ||
1017 | |||
1018 | if (IoAdapter->ControllerNumber > 0) | ||
1019 | return (-1); | ||
1020 | |||
1021 | p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); | ||
1022 | WRITE_BYTE(&p[PLX9054_INTCSR], PLX9054_INT_ENABLE); | ||
1023 | DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); | ||
1024 | /* | ||
1025 | interrupt test | ||
1026 | */ | ||
1027 | a->ReadyInt = 1; | ||
1028 | a->ram_out(a, &PR_RAM->ReadyInt, 1); | ||
1029 | |||
1030 | for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10)); | ||
1031 | |||
1032 | return ((IoAdapter->IrqCount > 0) ? 0 : -1); | ||
1033 | #else | ||
1034 | dword volatile __iomem *qBriIrq; | ||
1035 | byte __iomem *p; | ||
1036 | /* | ||
1037 | Reset on-board interrupt register | ||
1038 | */ | ||
1039 | IoAdapter->IrqCount = 0; | ||
1040 | p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); | ||
1041 | qBriIrq = (dword volatile __iomem *) (&p[_4bri_is_rev_2_card | ||
1042 | (IoAdapter-> | ||
1043 | cardType) ? (MQ2_BREG_IRQ_TEST) | ||
1044 | : (MQ_BREG_IRQ_TEST)]); | ||
1045 | |||
1046 | WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF); | ||
1047 | DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); | ||
1048 | |||
1049 | p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); | ||
1050 | WRITE_BYTE(&p[PLX9054_INTCSR], PLX9054_INT_ENABLE); | ||
1051 | DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); | ||
1052 | |||
1053 | diva_os_wait(100); | ||
1054 | |||
1055 | return (0); | ||
1056 | #endif /* SUPPORT_INTERRUPT_TEST_ON_4BRI */ | ||
1057 | } | ||
1058 | |||
1059 | static void diva_4bri_clear_interrupts(diva_os_xdi_adapter_t * a) | ||
1060 | { | ||
1061 | PISDN_ADAPTER IoAdapter = &a->xdi_adapter; | ||
1062 | |||
1063 | /* | ||
1064 | clear any pending interrupt | ||
1065 | */ | ||
1066 | IoAdapter->disIrq(IoAdapter); | ||
1067 | |||
1068 | IoAdapter->tst_irq(&IoAdapter->a); | ||
1069 | IoAdapter->clr_irq(&IoAdapter->a); | ||
1070 | IoAdapter->tst_irq(&IoAdapter->a); | ||
1071 | |||
1072 | /* | ||
1073 | kill pending dpcs | ||
1074 | */ | ||
1075 | diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr); | ||
1076 | diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr); | ||
1077 | } | ||
1078 | |||
1079 | static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t * a) | ||
1080 | { | ||
1081 | PISDN_ADAPTER IoAdapter = &a->xdi_adapter; | ||
1082 | int i; | ||
1083 | |||
1084 | if (!IoAdapter->ram) { | ||
1085 | return (-1); | ||
1086 | } | ||
1087 | |||
1088 | if (!IoAdapter->Initialized) { | ||
1089 | DBG_ERR(("A: A(%d) can't stop PRI adapter - not running", | ||
1090 | IoAdapter->ANum)) | ||
1091 | return (-1); /* nothing to stop */ | ||
1092 | } | ||
1093 | |||
1094 | for (i = 0; i < IoAdapter->tasks; i++) { | ||
1095 | IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0; | ||
1096 | } | ||
1097 | |||
1098 | /* | ||
1099 | Disconnect Adapters from DIDD | ||
1100 | */ | ||
1101 | for (i = 0; i < IoAdapter->tasks; i++) { | ||
1102 | diva_xdi_didd_remove_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum); | ||
1103 | } | ||
1104 | |||
1105 | i = 100; | ||
1106 | |||
1107 | /* | ||
1108 | Stop interrupts | ||
1109 | */ | ||
1110 | a->clear_interrupts_proc = diva_4bri_clear_interrupts; | ||
1111 | IoAdapter->a.ReadyInt = 1; | ||
1112 | IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt); | ||
1113 | do { | ||
1114 | diva_os_sleep(10); | ||
1115 | } while (i-- && a->clear_interrupts_proc); | ||
1116 | |||
1117 | if (a->clear_interrupts_proc) { | ||
1118 | diva_4bri_clear_interrupts(a); | ||
1119 | a->clear_interrupts_proc = NULL; | ||
1120 | DBG_ERR(("A: A(%d) no final interrupt from 4BRI adapter", | ||
1121 | IoAdapter->ANum)) | ||
1122 | } | ||
1123 | IoAdapter->a.ReadyInt = 0; | ||
1124 | |||
1125 | /* | ||
1126 | Stop and reset adapter | ||
1127 | */ | ||
1128 | IoAdapter->stop(IoAdapter); | ||
1129 | |||
1130 | return (0); | ||
1131 | } | ||