blob: 1891246807edfadffbdb6d1cacb0b9a776217ac3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* $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"
Adrian Bunk7019e7e2006-01-08 01:05:16 -080019#include "helpers.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
21static void *diva_xdiLoadFileFile = NULL;
22static dword diva_xdiLoadFileLength = 0;
23
24/*
25** IMPORTS
26*/
27extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter);
28extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter);
29extern void diva_xdi_display_adapter_features(int card);
Joe Perches475be4d2012-02-19 19:52:38 -080030extern void diva_add_slave_adapter(diva_os_xdi_adapter_t *a);
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
32extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter);
33extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter);
34
Joe Perches475be4d2012-02-19 19:52:38 -080035extern int diva_card_read_xlog(diva_os_xdi_adapter_t *a);
Linus Torvalds1da177e2005-04-16 15:20:36 -070036
37/*
38** LOCALS
39*/
40static unsigned long _4bri_bar_length[4] = {
41 0x100,
42 0x100, /* I/O */
43 MQ_MEMORY_SIZE,
44 0x2000
45};
46static unsigned long _4bri_v2_bar_length[4] = {
47 0x100,
48 0x100, /* I/O */
49 MQ2_MEMORY_SIZE,
50 0x10000
51};
52static unsigned long _4bri_v2_bri_bar_length[4] = {
53 0x100,
54 0x100, /* I/O */
55 BRI2_MEMORY_SIZE,
56 0x10000
57};
58
59
Joe Perches475be4d2012-02-19 19:52:38 -080060static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a);
61static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
Joe Perches475be4d2012-02-19 19:52:38 -080063 diva_xdi_um_cfg_cmd_t *cmd,
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 int length);
Joe Perches475be4d2012-02-19 19:52:38 -080065static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a);
66static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a,
67 byte *data, dword length);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter);
69static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
70 dword address,
Joe Perches475be4d2012-02-19 19:52:38 -080071 const byte *data,
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 dword length, dword limit);
73static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
74 dword start_address, dword features);
75static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter);
Joe Perches475be4d2012-02-19 19:52:38 -080076static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
78static int _4bri_is_rev_2_card(int card_ordinal)
79{
80 switch (card_ordinal) {
81 case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
82 case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
83 case CARDTYPE_DIVASRV_B_2M_V2_PCI:
84 case CARDTYPE_DIVASRV_B_2F_PCI:
85 case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
86 return (1);
87 }
88 return (0);
89}
90
91static int _4bri_is_rev_2_bri_card(int card_ordinal)
92{
93 switch (card_ordinal) {
94 case CARDTYPE_DIVASRV_B_2M_V2_PCI:
95 case CARDTYPE_DIVASRV_B_2F_PCI:
96 case CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI:
97 return (1);
98 }
99 return (0);
100}
101
102static void diva_4bri_set_addresses(diva_os_xdi_adapter_t *a)
103{
104 dword offset = a->resources.pci.qoffset;
105 dword c_offset = offset * a->xdi_adapter.ControllerNumber;
106
107 a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 2;
108 a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2;
109 a->resources.pci.mem_type_id[MEM_TYPE_CONTROL] = 2;
110 a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 0;
111 a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 3;
112 a->resources.pci.mem_type_id[MEM_TYPE_PROM] = 0;
113
114 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800115 Set up hardware related pointers
116 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 a->xdi_adapter.Address = a->resources.pci.addr[2]; /* BAR2 SDRAM */
118 a->xdi_adapter.Address += c_offset;
119
120 a->xdi_adapter.Control = a->resources.pci.addr[2]; /* BAR2 SDRAM */
121
122 a->xdi_adapter.ram = a->resources.pci.addr[2]; /* BAR2 SDRAM */
123 a->xdi_adapter.ram += c_offset + (offset - MQ_SHARED_RAM_SIZE);
Joe Perches475be4d2012-02-19 19:52:38 -0800124
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 a->xdi_adapter.reset = a->resources.pci.addr[0]; /* BAR0 CONFIG */
126 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800127 ctlReg contains the register address for the MIPS CPU reset control
128 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 a->xdi_adapter.ctlReg = a->resources.pci.addr[3]; /* BAR3 CNTRL */
130 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800131 prom contains the register address for FPGA and EEPROM programming
132 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E];
134}
135
136/*
137** BAR0 - MEM - 0x100 - CONFIG MEM
138** BAR1 - I/O - 0x100 - UNUSED
139** BAR2 - MEM - MQ_MEMORY_SIZE (MQ2_MEMORY_SIZE on Rev.2) - SDRAM
140** BAR3 - MEM - 0x2000 (0x10000 on Rev.2) - CNTRL
141**
142** Called by master adapter, that will initialize and add slave adapters
143*/
Joe Perches475be4d2012-02-19 19:52:38 -0800144int diva_4bri_init_card(diva_os_xdi_adapter_t *a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145{
146 int bar, i;
147 byte __iomem *p;
148 PADAPTER_LIST_ENTRY quadro_list;
149 diva_os_xdi_adapter_t *diva_current;
150 diva_os_xdi_adapter_t *adapter_list[4];
151 PISDN_ADAPTER Slave;
Karsten Keilba2d6cc2009-07-24 18:26:08 +0200152 unsigned long bar_length[ARRAY_SIZE(_4bri_bar_length)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 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
Joe Perches475be4d2012-02-19 19:52:38 -0800171 /*
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 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
183 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800184 Set properties
185 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 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
Joe Perches475be4d2012-02-19 19:52:38 -0800192 /*
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 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 a->resources.pci.irq =
Joe Perches475be4d2012-02-19 19:52:38 -0800210 (byte) divasa_get_pci_irq(a->resources.pci.bus,
211 a->resources.pci.func,
212 a->resources.pci.hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 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 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800221 Map all MEMORY BAR's
222 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 for (bar = 0; bar < 4; bar++) {
224 if (bar != 1) { /* ignore I/O */
225 a->resources.pci.addr[bar] =
Joe Perches475be4d2012-02-19 19:52:38 -0800226 divasa_remap_pci_bar(a, bar, a->resources.pci.bar[bar],
227 bar_length[bar]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 if (!a->resources.pci.addr[bar]) {
229 DBG_ERR(("A: 4BRI: can't map bar[%d]", bar))
Joe Perches475be4d2012-02-19 19:52:38 -0800230 diva_4bri_cleanup_adapter(a);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 return (-1);
232 }
233 }
234 }
235
236 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800237 Register I/O port
238 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 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]"))
Joe Perches475be4d2012-02-19 19:52:38 -0800244 diva_4bri_cleanup_adapter(a);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 return (-1);
246 }
247
248 a->resources.pci.addr[1] =
249 (void *) (unsigned long) a->resources.pci.bar[1];
250
251 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800252 Set cleanup pointer for base adapter only, so slave adapter
253 will be unable to get cleanup
254 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 a->interface.cleanup_adapter_proc = diva_4bri_cleanup_adapter;
256
257 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800258 Create slave adapters
259 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 if (tasks > 1) {
261 if (!(a->slave_adapters[0] =
Joe Perches475be4d2012-02-19 19:52:38 -0800262 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 {
264 diva_4bri_cleanup_adapter(a);
265 return (-1);
266 }
267 if (!(a->slave_adapters[1] =
Joe Perches475be4d2012-02-19 19:52:38 -0800268 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 {
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] =
Joe Perches475be4d2012-02-19 19:52:38 -0800276 (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a))))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 {
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 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800296 Allocate slave list
297 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 quadro_list =
Joe Perches475be4d2012-02-19 19:52:38 -0800299 (PADAPTER_LIST_ENTRY) diva_os_malloc(0, sizeof(*quadro_list));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 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 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800311 Set interfaces
312 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313 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] =
Joe Perches475be4d2012-02-19 19:52:38 -0800318 &adapter_list[i]->xdi_adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 }
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 =
Joe Perches475be4d2012-02-19 19:52:38 -0800327 &diva_current->xdi_adapter;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 diva_current->xdi_adapter.DIRequest = request;
329 diva_current->interface.cmd_proc = diva_4bri_cmd_card_proc;
330 diva_current->xdi_adapter.Properties =
Joe Perches475be4d2012-02-19 19:52:38 -0800331 CardProperties[a->CardOrdinal];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 diva_current->CardOrdinal = a->CardOrdinal;
333
334 diva_current->xdi_adapter.Channels =
Joe Perches475be4d2012-02-19 19:52:38 -0800335 CardProperties[a->CardOrdinal].Channels;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 diva_current->xdi_adapter.e_max =
Joe Perches475be4d2012-02-19 19:52:38 -0800337 CardProperties[a->CardOrdinal].E_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 diva_current->xdi_adapter.e_tbl =
Joe Perches475be4d2012-02-19 19:52:38 -0800339 diva_os_malloc(0,
340 diva_current->xdi_adapter.e_max *
341 sizeof(E_INFO));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
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
Joe Perches475be4d2012-02-19 19:52:38 -0800373 if (diva_os_initialize_soft_isr(&diva_current->xdi_adapter.req_soft_isr, DIDpcRoutine,
374 &diva_current->xdi_adapter)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 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 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800384 Do not initialize second DPC - only one thread will be created
385 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 diva_current->xdi_adapter.isr_soft_isr.object =
Joe Perches475be4d2012-02-19 19:52:38 -0800387 diva_current->xdi_adapter.req_soft_isr.object;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 }
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));
Joe Perches475be4d2012-02-19 19:52:38 -0800400 diva_current->resources.pci.qoffset = (a->xdi_adapter.MemorySize >> factor);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 }
402
403 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800404 Set up hardware related pointers
405 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 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)) |
Joe Perches475be4d2012-02-19 19:52:38 -0800418 a->xdi_adapter.serialNo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 Slave->cardType = a->xdi_adapter.cardType;
420 }
421 }
422
423 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800424 reset contains the base address for the PLX 9054 register set
425 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 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 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800431 Set IRQ handler
432 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 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 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800450 Add three slave adapters
451 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 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
Matt LaPlante0779bf22006-11-30 05:24:39 +0100466** this is guaranteed by design: cleanup callback is set
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467** by master adapter only
468*/
Joe Perches475be4d2012-02-19 19:52:38 -0800469static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470{
471 int bar;
472
473 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800474 Stop adapter if running
475 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 if (a->xdi_adapter.Initialized) {
477 diva_4bri_stop_adapter(a);
478 }
479
480 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800481 Remove IRQ handler
482 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 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 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800489 Free DPC's and spin locks on all adapters
490 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 diva_4bri_cleanup_slave_adapters(a);
492
493 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800494 Unmap all BARS
495 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 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 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800508 Unregister I/O
509 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 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
Joe Perches475be4d2012-02-19 19:52:38 -0800529static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530{
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))
Joe Perches475be4d2012-02-19 19:52:38 -0800554 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 }
556 PCIread(Bus, Slot, 0x50, &data[i], sizeof(data[i]), hdev);
557 }
558 DBG_BLK(((char *) &data[0], sizeof(data)))
559
Joe Perches475be4d2012-02-19 19:52:38 -0800560 serNo = data[32];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 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
Joe Perches475be4d2012-02-19 19:52:38 -0800575 return (serNo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576}
577
578/*
579** Release resources of slave adapters
580*/
Joe Perches475be4d2012-02-19 19:52:38 -0800581static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582{
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
626static int
627diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
Joe Perches475be4d2012-02-19 19:52:38 -0800628 diva_xdi_um_cfg_cmd_t *cmd, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629{
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))
Joe Perches475be4d2012-02-19 19:52:38 -0800635 return (-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 }
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 =
Joe Perches475be4d2012-02-19 19:52:38 -0800642 diva_os_malloc(0, a->xdi_mbox.data_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 if (a->xdi_mbox.data) {
644 *(dword *) a->xdi_mbox.data =
Joe Perches475be4d2012-02-19 19:52:38 -0800645 (dword) a->CardOrdinal;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 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 =
Joe Perches475be4d2012-02-19 19:52:38 -0800654 diva_os_malloc(0, a->xdi_mbox.data_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 if (a->xdi_mbox.data) {
656 *(dword *) a->xdi_mbox.data =
Joe Perches475be4d2012-02-19 19:52:38 -0800657 (dword) a->xdi_adapter.serialNo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 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 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800666 Only master adapter can access hardware config
667 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 a->xdi_mbox.data_length = sizeof(dword) * 9;
669 a->xdi_mbox.data =
Joe Perches475be4d2012-02-19 19:52:38 -0800670 diva_os_malloc(0, a->xdi_mbox.data_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 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 =
Joe Perches475be4d2012-02-19 19:52:38 -0800689 diva_os_malloc(0, a->xdi_mbox.data_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 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 =
Joe Perches475be4d2012-02-19 19:52:38 -0800712 diva_4bri_write_fpga_image(a,
713 (byte *)&cmd[1],
714 cmd->command_data.
715 write_fpga.
716 image_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 }
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 =
Joe Perches475be4d2012-02-19 19:52:38 -0800757 cmd->command_data.features.features;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 a->xdi_adapter.a.protocol_capabilities =
Joe Perches475be4d2012-02-19 19:52:38 -0800759 a->xdi_adapter.features;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 DBG_TRC(("Set raw protocol features (%08x)",
761 a->xdi_adapter.features))
Joe Perches475be4d2012-02-19 19:52:38 -0800762 ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 }
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 (
Joe Perches475be4d2012-02-19 19:52:38 -0800780 (a->xdi_mbox.data_length =
781 cmd->command_data.read_sdram.length)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 if (
Joe Perches475be4d2012-02-19 19:52:38 -0800783 (a->xdi_mbox.data_length +
784 cmd->command_data.read_sdram.offset) <
785 a->xdi_adapter.MemorySize) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 a->xdi_mbox.data =
Joe Perches475be4d2012-02-19 19:52:38 -0800787 diva_os_malloc(0,
788 a->xdi_mbox.
789 data_length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 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))
Joe Perches475be4d2012-02-19 19:52:38 -0800813 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814
815 return (ret);
816}
817
Adrian Bunk7019e7e2006-01-08 01:05:16 -0800818void *xdiLoadFile(char *FileName, dword *FileLength,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 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
832void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter)
833{
834}
835
836void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter)
837{
838}
839
840static int
Joe Perches475be4d2012-02-19 19:52:38 -0800841diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a, byte *data,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 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
857static 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))
Joe Perches475be4d2012-02-19 19:52:38 -0800868 return (-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 }
870
871 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800872 Forget all entities on all adapters
873 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 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
908static int
909diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
910 dword address,
Joe Perches475be4d2012-02-19 19:52:38 -0800911 const byte *data, dword length, dword limit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912{
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))
Joe Perches475be4d2012-02-19 19:52:38 -0800920 return (-1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 }
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
932static int
933diva_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 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800942 start adapter
943 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 start_qBri_hardware(IoAdapter);
945
946 p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
947 /*
Joe Perches475be4d2012-02-19 19:52:38 -0800948 wait for signature in shared memory (max. 3 seconds)
949 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 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)))
Joe Perches475be4d2012-02-19 19:52:38 -0800957 started = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 break;
959 }
960 }
961
962 for (i = 1; i < IoAdapter->tasks; i++) {
963 IoAdapter->QuadroList->QuadroAdapter[i]->features =
Joe Perches475be4d2012-02-19 19:52:38 -0800964 IoAdapter->features;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 IoAdapter->QuadroList->QuadroAdapter[i]->a.
Joe Perches475be4d2012-02-19 19:52:38 -0800966 protocol_capabilities = IoAdapter->features;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 }
968
969 if (!started) {
970 DBG_FTL(("%s: Adapter selftest failed, signature=%04x",
971 IoAdapter->Properties.Name,
972 READ_WORD(&signature[0])))
Joe Perches475be4d2012-02-19 19:52:38 -0800973 DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 (*(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))
Joe Perches475be4d2012-02-19 19:52:38 -0800988 for (i = 0; i < IoAdapter->tasks; i++) {
989 IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
990 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 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++) {
Coly Li73ac36e2009-01-07 18:09:16 -0800999 DBG_LOG(("A(%d) %s adapter successfully started",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 IoAdapter->QuadroList->QuadroAdapter[i]->ANum,
1001 (IoAdapter->tasks == 1) ? "BRI 2.0" : "4BRI"))
Joe Perches475be4d2012-02-19 19:52:38 -08001002 diva_xdi_didd_register_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 IoAdapter->QuadroList->QuadroAdapter[i]->Properties.Features = (word) features;
1004 }
1005
1006 return (0);
1007}
1008
1009static 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 /*
Joe Perches475be4d2012-02-19 19:52:38 -08001025 interrupt test
1026 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 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 /*
Joe Perches475be4d2012-02-19 19:52:38 -08001037 Reset on-board interrupt register
1038 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 IoAdapter->IrqCount = 0;
1040 p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
1041 qBriIrq = (dword volatile __iomem *) (&p[_4bri_is_rev_2_card
Joe Perches475be4d2012-02-19 19:52:38 -08001042 (IoAdapter->
1043 cardType) ? (MQ2_BREG_IRQ_TEST)
1044 : (MQ_BREG_IRQ_TEST)]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
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
Joe Perches475be4d2012-02-19 19:52:38 -08001059static void diva_4bri_clear_interrupts(diva_os_xdi_adapter_t *a)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060{
1061 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1062
1063 /*
Joe Perches475be4d2012-02-19 19:52:38 -08001064 clear any pending interrupt
1065 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 IoAdapter->disIrq(IoAdapter);
1067
1068 IoAdapter->tst_irq(&IoAdapter->a);
1069 IoAdapter->clr_irq(&IoAdapter->a);
1070 IoAdapter->tst_irq(&IoAdapter->a);
1071
1072 /*
Joe Perches475be4d2012-02-19 19:52:38 -08001073 kill pending dpcs
1074 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
1076 diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
1077}
1078
Joe Perches475be4d2012-02-19 19:52:38 -08001079static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080{
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))
Joe Perches475be4d2012-02-19 19:52:38 -08001091 return (-1); /* nothing to stop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 }
1093
1094 for (i = 0; i < IoAdapter->tasks; i++) {
1095 IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
1096 }
1097
1098 /*
Joe Perches475be4d2012-02-19 19:52:38 -08001099 Disconnect Adapters from DIDD
1100 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 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 /*
Joe Perches475be4d2012-02-19 19:52:38 -08001108 Stop interrupts
1109 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 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))
Joe Perches475be4d2012-02-19 19:52:38 -08001122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 IoAdapter->a.ReadyInt = 0;
1124
1125 /*
Joe Perches475be4d2012-02-19 19:52:38 -08001126 Stop and reset adapter
1127 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 IoAdapter->stop(IoAdapter);
1129
1130 return (0);
1131}