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#include "helpers.h"
20
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);
30extern void diva_add_slave_adapter(diva_os_xdi_adapter_t *a);
31
32extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter);
33extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter);
34
35extern int diva_card_read_xlog(diva_os_xdi_adapter_t *a);
36
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
60static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a);
61static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a);
62static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
63				   diva_xdi_um_cfg_cmd_t *cmd,
64				   int length);
65static 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);
68static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter);
69static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
70				       dword address,
71				       const byte *data,
72				       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);
76static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a);
77
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	/*
115	  Set up hardware related pointers
116	*/
117	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);
124
125	a->xdi_adapter.reset = a->resources.pci.addr[0];	/* BAR0 CONFIG */
126	/*
127	  ctlReg contains the register address for the MIPS CPU reset control
128	*/
129	a->xdi_adapter.ctlReg = a->resources.pci.addr[3];	/* BAR3 CNTRL  */
130	/*
131	  prom contains the register address for FPGA and EEPROM programming
132	*/
133	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*/
144int diva_4bri_init_card(diva_os_xdi_adapter_t *a)
145{
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;
152	unsigned long bar_length[ARRAY_SIZE(_4bri_bar_length)];
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 guaranteed by design: cleanup callback is set
467**  by master adapter only
468*/
469static 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
529static 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*/
581static 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
626static int
627diva_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
818void *xdiLoadFile(char *FileName, dword *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
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
841diva_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
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))
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
908static int
909diva_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
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	/*
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 successfully 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
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	/*
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
1059static 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
1079static 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}
1132