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