• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
21 static void *diva_xdiLoadFileFile = NULL;
22 static dword diva_xdiLoadFileLength = 0;
23 
24 /*
25 **  IMPORTS
26 */
27 extern void prepare_qBri_functions(PISDN_ADAPTER IoAdapter);
28 extern void prepare_qBri2_functions(PISDN_ADAPTER IoAdapter);
29 extern void diva_xdi_display_adapter_features(int card);
30 extern void diva_add_slave_adapter(diva_os_xdi_adapter_t *a);
31 
32 extern int qBri_FPGA_download(PISDN_ADAPTER IoAdapter);
33 extern void start_qBri_hardware(PISDN_ADAPTER IoAdapter);
34 
35 extern int diva_card_read_xlog(diva_os_xdi_adapter_t *a);
36 
37 /*
38 **  LOCALS
39 */
40 static unsigned long _4bri_bar_length[4] = {
41 	0x100,
42 	0x100,			/* I/O */
43 	MQ_MEMORY_SIZE,
44 	0x2000
45 };
46 static unsigned long _4bri_v2_bar_length[4] = {
47 	0x100,
48 	0x100,			/* I/O */
49 	MQ2_MEMORY_SIZE,
50 	0x10000
51 };
52 static unsigned long _4bri_v2_bri_bar_length[4] = {
53 	0x100,
54 	0x100,			/* I/O */
55 	BRI2_MEMORY_SIZE,
56 	0x10000
57 };
58 
59 
60 static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a);
61 static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a);
62 static int diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
63 				   diva_xdi_um_cfg_cmd_t *cmd,
64 				   int length);
65 static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a);
66 static int diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a,
67 				      byte *data, dword length);
68 static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter);
69 static int diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
70 				       dword address,
71 				       const byte *data,
72 				       dword length, dword limit);
73 static int diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
74 				   dword start_address, dword features);
75 static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter);
76 static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a);
77 
_4bri_is_rev_2_card(int card_ordinal)78 static 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 
_4bri_is_rev_2_bri_card(int card_ordinal)91 static 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 
diva_4bri_set_addresses(diva_os_xdi_adapter_t * a)102 static 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 */
diva_4bri_init_card(diva_os_xdi_adapter_t * a)144 int 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 */
diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a)469 static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t *a)
470 {
471 	int bar;
472 
473 	/*
474 	  Stop adapter if running
475 	*/
476 	if (a->xdi_adapter.Initialized) {
477 		diva_4bri_stop_adapter(a);
478 	}
479 
480 	/*
481 	  Remove IRQ handler
482 	*/
483 	if (a->xdi_adapter.irq_info.registered) {
484 		diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
485 	}
486 	a->xdi_adapter.irq_info.registered = 0;
487 
488 	/*
489 	  Free DPC's and spin locks on all adapters
490 	*/
491 	diva_4bri_cleanup_slave_adapters(a);
492 
493 	/*
494 	  Unmap all BARS
495 	*/
496 	for (bar = 0; bar < 4; bar++) {
497 		if (bar != 1) {
498 			if (a->resources.pci.bar[bar]
499 			    && a->resources.pci.addr[bar]) {
500 				divasa_unmap_pci_bar(a->resources.pci.addr[bar]);
501 				a->resources.pci.bar[bar] = 0;
502 				a->resources.pci.addr[bar] = NULL;
503 			}
504 		}
505 	}
506 
507 	/*
508 	  Unregister I/O
509 	*/
510 	if (a->resources.pci.bar[1] && a->resources.pci.addr[1]) {
511 		diva_os_register_io_port(a, 0, a->resources.pci.bar[1],
512 					 _4bri_is_rev_2_card(a->
513 							     CardOrdinal) ?
514 					 _4bri_v2_bar_length[1] :
515 					 _4bri_bar_length[1],
516 					 &a->port_name[0], 1);
517 		a->resources.pci.bar[1] = 0;
518 		a->resources.pci.addr[1] = NULL;
519 	}
520 
521 	if (a->slave_list) {
522 		diva_os_free(0, a->slave_list);
523 		a->slave_list = NULL;
524 	}
525 
526 	return (0);
527 }
528 
_4bri_get_serial_number(diva_os_xdi_adapter_t * a)529 static int _4bri_get_serial_number(diva_os_xdi_adapter_t *a)
530 {
531 	dword data[64];
532 	dword serNo;
533 	word addr, status, i, j;
534 	byte Bus, Slot;
535 	void *hdev;
536 
537 	Bus = a->resources.pci.bus;
538 	Slot = a->resources.pci.func;
539 	hdev = a->resources.pci.hdev;
540 
541 	for (i = 0; i < 64; ++i) {
542 		addr = i * 4;
543 		for (j = 0; j < 5; ++j) {
544 			PCIwrite(Bus, Slot, 0x4E, &addr, sizeof(addr),
545 				 hdev);
546 			diva_os_wait(1);
547 			PCIread(Bus, Slot, 0x4E, &status, sizeof(status),
548 				hdev);
549 			if (status & 0x8000)
550 				break;
551 		}
552 		if (j >= 5) {
553 			DBG_ERR(("EEPROM[%d] read failed (0x%x)", i * 4, addr))
554 				return (0);
555 		}
556 		PCIread(Bus, Slot, 0x50, &data[i], sizeof(data[i]), hdev);
557 	}
558 	DBG_BLK(((char *) &data[0], sizeof(data)))
559 
560 		serNo = data[32];
561 	if (serNo == 0 || serNo == 0xffffffff)
562 		serNo = data[63];
563 
564 	if (!serNo) {
565 		DBG_LOG(("W: Serial Number == 0, create one serial number"));
566 		serNo = a->resources.pci.bar[1] & 0xffff0000;
567 		serNo |= a->resources.pci.bus << 8;
568 		serNo |= a->resources.pci.func;
569 	}
570 
571 	a->xdi_adapter.serialNo = serNo;
572 
573 	DBG_REG(("Serial No.          : %ld", a->xdi_adapter.serialNo))
574 
575 		return (serNo);
576 }
577 
578 /*
579 **  Release resources of slave adapters
580 */
diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t * a)581 static int diva_4bri_cleanup_slave_adapters(diva_os_xdi_adapter_t *a)
582 {
583 	diva_os_xdi_adapter_t *adapter_list[4];
584 	diva_os_xdi_adapter_t *diva_current;
585 	int i;
586 
587 	adapter_list[0] = a;
588 	adapter_list[1] = a->slave_adapters[0];
589 	adapter_list[2] = a->slave_adapters[1];
590 	adapter_list[3] = a->slave_adapters[2];
591 
592 	for (i = 0; i < a->xdi_adapter.tasks; i++) {
593 		diva_current = adapter_list[i];
594 		if (diva_current) {
595 			diva_os_destroy_spin_lock(&diva_current->
596 						  xdi_adapter.
597 						  isr_spin_lock, "unload");
598 			diva_os_destroy_spin_lock(&diva_current->
599 						  xdi_adapter.
600 						  data_spin_lock,
601 						  "unload");
602 
603 			diva_os_cancel_soft_isr(&diva_current->xdi_adapter.
604 						req_soft_isr);
605 			diva_os_cancel_soft_isr(&diva_current->xdi_adapter.
606 						isr_soft_isr);
607 
608 			diva_os_remove_soft_isr(&diva_current->xdi_adapter.
609 						req_soft_isr);
610 			diva_current->xdi_adapter.isr_soft_isr.object = NULL;
611 
612 			if (diva_current->xdi_adapter.e_tbl) {
613 				diva_os_free(0,
614 					     diva_current->xdi_adapter.
615 					     e_tbl);
616 			}
617 			diva_current->xdi_adapter.e_tbl = NULL;
618 			diva_current->xdi_adapter.e_max = 0;
619 			diva_current->xdi_adapter.e_count = 0;
620 		}
621 	}
622 
623 	return (0);
624 }
625 
626 static int
diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter * a,diva_xdi_um_cfg_cmd_t * cmd,int length)627 diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
628 			diva_xdi_um_cfg_cmd_t *cmd, int length)
629 {
630 	int ret = -1;
631 
632 	if (cmd->adapter != a->controller) {
633 		DBG_ERR(("A: 4bri_cmd, invalid controller=%d != %d",
634 			 cmd->adapter, a->controller))
635 			return (-1);
636 	}
637 
638 	switch (cmd->command) {
639 	case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
640 		a->xdi_mbox.data_length = sizeof(dword);
641 		a->xdi_mbox.data =
642 			diva_os_malloc(0, a->xdi_mbox.data_length);
643 		if (a->xdi_mbox.data) {
644 			*(dword *) a->xdi_mbox.data =
645 				(dword) a->CardOrdinal;
646 			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
647 			ret = 0;
648 		}
649 		break;
650 
651 	case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
652 		a->xdi_mbox.data_length = sizeof(dword);
653 		a->xdi_mbox.data =
654 			diva_os_malloc(0, a->xdi_mbox.data_length);
655 		if (a->xdi_mbox.data) {
656 			*(dword *) a->xdi_mbox.data =
657 				(dword) a->xdi_adapter.serialNo;
658 			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
659 			ret = 0;
660 		}
661 		break;
662 
663 	case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
664 		if (!a->xdi_adapter.ControllerNumber) {
665 			/*
666 			  Only master adapter can access hardware config
667 			*/
668 			a->xdi_mbox.data_length = sizeof(dword) * 9;
669 			a->xdi_mbox.data =
670 				diva_os_malloc(0, a->xdi_mbox.data_length);
671 			if (a->xdi_mbox.data) {
672 				int i;
673 				dword *data = (dword *) a->xdi_mbox.data;
674 
675 				for (i = 0; i < 8; i++) {
676 					*data++ = a->resources.pci.bar[i];
677 				}
678 				*data++ = (dword) a->resources.pci.irq;
679 				a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
680 				ret = 0;
681 			}
682 		}
683 		break;
684 
685 	case DIVA_XDI_UM_CMD_GET_CARD_STATE:
686 		if (!a->xdi_adapter.ControllerNumber) {
687 			a->xdi_mbox.data_length = sizeof(dword);
688 			a->xdi_mbox.data =
689 				diva_os_malloc(0, a->xdi_mbox.data_length);
690 			if (a->xdi_mbox.data) {
691 				dword *data = (dword *) a->xdi_mbox.data;
692 				if (!a->xdi_adapter.ram
693 				    || !a->xdi_adapter.reset
694 				    || !a->xdi_adapter.cfg) {
695 					*data = 3;
696 				} else if (a->xdi_adapter.trapped) {
697 					*data = 2;
698 				} else if (a->xdi_adapter.Initialized) {
699 					*data = 1;
700 				} else {
701 					*data = 0;
702 				}
703 				a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
704 				ret = 0;
705 			}
706 		}
707 		break;
708 
709 	case DIVA_XDI_UM_CMD_WRITE_FPGA:
710 		if (!a->xdi_adapter.ControllerNumber) {
711 			ret =
712 				diva_4bri_write_fpga_image(a,
713 							   (byte *)&cmd[1],
714 							   cmd->command_data.
715 							   write_fpga.
716 							   image_length);
717 		}
718 		break;
719 
720 	case DIVA_XDI_UM_CMD_RESET_ADAPTER:
721 		if (!a->xdi_adapter.ControllerNumber) {
722 			ret = diva_4bri_reset_adapter(&a->xdi_adapter);
723 		}
724 		break;
725 
726 	case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
727 		if (!a->xdi_adapter.ControllerNumber) {
728 			ret = diva_4bri_write_sdram_block(&a->xdi_adapter,
729 							  cmd->
730 							  command_data.
731 							  write_sdram.
732 							  offset,
733 							  (byte *) &
734 							  cmd[1],
735 							  cmd->
736 							  command_data.
737 							  write_sdram.
738 							  length,
739 							  a->xdi_adapter.
740 							  MemorySize);
741 		}
742 		break;
743 
744 	case DIVA_XDI_UM_CMD_START_ADAPTER:
745 		if (!a->xdi_adapter.ControllerNumber) {
746 			ret = diva_4bri_start_adapter(&a->xdi_adapter,
747 						      cmd->command_data.
748 						      start.offset,
749 						      cmd->command_data.
750 						      start.features);
751 		}
752 		break;
753 
754 	case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
755 		if (!a->xdi_adapter.ControllerNumber) {
756 			a->xdi_adapter.features =
757 				cmd->command_data.features.features;
758 			a->xdi_adapter.a.protocol_capabilities =
759 				a->xdi_adapter.features;
760 			DBG_TRC(("Set raw protocol features (%08x)",
761 				 a->xdi_adapter.features))
762 				ret = 0;
763 		}
764 		break;
765 
766 	case DIVA_XDI_UM_CMD_STOP_ADAPTER:
767 		if (!a->xdi_adapter.ControllerNumber) {
768 			ret = diva_4bri_stop_adapter(a);
769 		}
770 		break;
771 
772 	case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
773 		ret = diva_card_read_xlog(a);
774 		break;
775 
776 	case DIVA_XDI_UM_CMD_READ_SDRAM:
777 		if (!a->xdi_adapter.ControllerNumber
778 		    && a->xdi_adapter.Address) {
779 			if (
780 				(a->xdi_mbox.data_length =
781 				 cmd->command_data.read_sdram.length)) {
782 				if (
783 					(a->xdi_mbox.data_length +
784 					 cmd->command_data.read_sdram.offset) <
785 					a->xdi_adapter.MemorySize) {
786 					a->xdi_mbox.data =
787 						diva_os_malloc(0,
788 							       a->xdi_mbox.
789 							       data_length);
790 					if (a->xdi_mbox.data) {
791 						byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter);
792 						byte __iomem *src = p;
793 						byte *dst = a->xdi_mbox.data;
794 						dword len = a->xdi_mbox.data_length;
795 
796 						src += cmd->command_data.read_sdram.offset;
797 
798 						while (len--) {
799 							*dst++ = READ_BYTE(src++);
800 						}
801 						DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p);
802 						a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
803 						ret = 0;
804 					}
805 				}
806 			}
807 		}
808 		break;
809 
810 	default:
811 		DBG_ERR(("A: A(%d) invalid cmd=%d", a->controller,
812 			 cmd->command))
813 			}
814 
815 	return (ret);
816 }
817 
xdiLoadFile(char * FileName,dword * FileLength,unsigned long lim)818 void *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 
diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter)832 void diva_os_set_qBri_functions(PISDN_ADAPTER IoAdapter)
833 {
834 }
835 
diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter)836 void diva_os_set_qBri2_functions(PISDN_ADAPTER IoAdapter)
837 {
838 }
839 
840 static int
diva_4bri_write_fpga_image(diva_os_xdi_adapter_t * a,byte * data,dword length)841 diva_4bri_write_fpga_image(diva_os_xdi_adapter_t *a, byte *data,
842 			   dword length)
843 {
844 	int ret;
845 
846 	diva_xdiLoadFileFile = data;
847 	diva_xdiLoadFileLength = length;
848 
849 	ret = qBri_FPGA_download(&a->xdi_adapter);
850 
851 	diva_xdiLoadFileFile = NULL;
852 	diva_xdiLoadFileLength = 0;
853 
854 	return (ret ? 0 : -1);
855 }
856 
diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter)857 static int diva_4bri_reset_adapter(PISDN_ADAPTER IoAdapter)
858 {
859 	PISDN_ADAPTER Slave;
860 	int i;
861 
862 	if (!IoAdapter->Address || !IoAdapter->reset) {
863 		return (-1);
864 	}
865 	if (IoAdapter->Initialized) {
866 		DBG_ERR(("A: A(%d) can't reset 4BRI adapter - please stop first",
867 			 IoAdapter->ANum))
868 			return (-1);
869 	}
870 
871 	/*
872 	  Forget all entities on all adapters
873 	*/
874 	for (i = 0; ((i < IoAdapter->tasks) && IoAdapter->QuadroList); i++) {
875 		Slave = IoAdapter->QuadroList->QuadroAdapter[i];
876 		Slave->e_count = 0;
877 		if (Slave->e_tbl) {
878 			memset(Slave->e_tbl, 0x00,
879 			       Slave->e_max * sizeof(E_INFO));
880 		}
881 		Slave->head = 0;
882 		Slave->tail = 0;
883 		Slave->assign = 0;
884 		Slave->trapped = 0;
885 
886 		memset(&Slave->a.IdTable[0], 0x00,
887 		       sizeof(Slave->a.IdTable));
888 		memset(&Slave->a.IdTypeTable[0], 0x00,
889 		       sizeof(Slave->a.IdTypeTable));
890 		memset(&Slave->a.FlowControlIdTable[0], 0x00,
891 		       sizeof(Slave->a.FlowControlIdTable));
892 		memset(&Slave->a.FlowControlSkipTable[0], 0x00,
893 		       sizeof(Slave->a.FlowControlSkipTable));
894 		memset(&Slave->a.misc_flags_table[0], 0x00,
895 		       sizeof(Slave->a.misc_flags_table));
896 		memset(&Slave->a.rx_stream[0], 0x00,
897 		       sizeof(Slave->a.rx_stream));
898 		memset(&Slave->a.tx_stream[0], 0x00,
899 		       sizeof(Slave->a.tx_stream));
900 		memset(&Slave->a.tx_pos[0], 0x00, sizeof(Slave->a.tx_pos));
901 		memset(&Slave->a.rx_pos[0], 0x00, sizeof(Slave->a.rx_pos));
902 	}
903 
904 	return (0);
905 }
906 
907 
908 static int
diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,dword address,const byte * data,dword length,dword limit)909 diva_4bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
910 			    dword address,
911 			    const byte *data, dword length, dword limit)
912 {
913 	byte __iomem *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter);
914 	byte __iomem *mem = p;
915 
916 	if (((address + length) >= limit) || !mem) {
917 		DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
918 		DBG_ERR(("A: A(%d) write 4BRI address=0x%08lx",
919 			 IoAdapter->ANum, address + length))
920 			return (-1);
921 	}
922 	mem += address;
923 
924 	while (length--) {
925 		WRITE_BYTE(mem++, *data++);
926 	}
927 
928 	DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p);
929 	return (0);
930 }
931 
932 static int
diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,dword start_address,dword features)933 diva_4bri_start_adapter(PISDN_ADAPTER IoAdapter,
934 			dword start_address, dword features)
935 {
936 	volatile word __iomem *signature;
937 	int started = 0;
938 	int i;
939 	byte __iomem *p;
940 
941 	/*
942 	  start adapter
943 	*/
944 	start_qBri_hardware(IoAdapter);
945 
946 	p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter);
947 	/*
948 	  wait for signature in shared memory (max. 3 seconds)
949 	*/
950 	signature = (volatile word __iomem *) (&p[0x1E]);
951 
952 	for (i = 0; i < 300; ++i) {
953 		diva_os_wait(10);
954 		if (READ_WORD(&signature[0]) == 0x4447) {
955 			DBG_TRC(("Protocol startup time %d.%02d seconds",
956 				 (i / 100), (i % 100)))
957 				started = 1;
958 			break;
959 		}
960 	}
961 
962 	for (i = 1; i < IoAdapter->tasks; i++) {
963 		IoAdapter->QuadroList->QuadroAdapter[i]->features =
964 			IoAdapter->features;
965 		IoAdapter->QuadroList->QuadroAdapter[i]->a.
966 			protocol_capabilities = IoAdapter->features;
967 	}
968 
969 	if (!started) {
970 		DBG_FTL(("%s: Adapter selftest failed, signature=%04x",
971 			 IoAdapter->Properties.Name,
972 			 READ_WORD(&signature[0])))
973 			DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
974 		(*(IoAdapter->trapFnc)) (IoAdapter);
975 		IoAdapter->stop(IoAdapter);
976 		return (-1);
977 	}
978 	DIVA_OS_MEM_DETACH_RAM(IoAdapter, p);
979 
980 	for (i = 0; i < IoAdapter->tasks; i++) {
981 		IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 1;
982 		IoAdapter->QuadroList->QuadroAdapter[i]->IrqCount = 0;
983 	}
984 
985 	if (check_qBri_interrupt(IoAdapter)) {
986 		DBG_ERR(("A: A(%d) interrupt test failed",
987 			 IoAdapter->ANum))
988 			for (i = 0; i < IoAdapter->tasks; i++) {
989 				IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
990 			}
991 		IoAdapter->stop(IoAdapter);
992 		return (-1);
993 	}
994 
995 	IoAdapter->Properties.Features = (word) features;
996 	diva_xdi_display_adapter_features(IoAdapter->ANum);
997 
998 	for (i = 0; i < IoAdapter->tasks; i++) {
999 		DBG_LOG(("A(%d) %s adapter 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 
check_qBri_interrupt(PISDN_ADAPTER IoAdapter)1009 static int check_qBri_interrupt(PISDN_ADAPTER IoAdapter)
1010 {
1011 #ifdef	SUPPORT_INTERRUPT_TEST_ON_4BRI
1012 	int i;
1013 	ADAPTER *a = &IoAdapter->a;
1014 	byte __iomem *p;
1015 
1016 	IoAdapter->IrqCount = 0;
1017 
1018 	if (IoAdapter->ControllerNumber > 0)
1019 		return (-1);
1020 
1021 	p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
1022 	WRITE_BYTE(&p[PLX9054_INTCSR], PLX9054_INT_ENABLE);
1023 	DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
1024 	/*
1025 	  interrupt test
1026 	*/
1027 	a->ReadyInt = 1;
1028 	a->ram_out(a, &PR_RAM->ReadyInt, 1);
1029 
1030 	for (i = 100; !IoAdapter->IrqCount && (i-- > 0); diva_os_wait(10));
1031 
1032 	return ((IoAdapter->IrqCount > 0) ? 0 : -1);
1033 #else
1034 	dword volatile __iomem *qBriIrq;
1035 	byte __iomem *p;
1036 	/*
1037 	  Reset on-board interrupt register
1038 	*/
1039 	IoAdapter->IrqCount = 0;
1040 	p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
1041 	qBriIrq = (dword volatile __iomem *) (&p[_4bri_is_rev_2_card
1042 						 (IoAdapter->
1043 						  cardType) ? (MQ2_BREG_IRQ_TEST)
1044 						 : (MQ_BREG_IRQ_TEST)]);
1045 
1046 	WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF);
1047 	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p);
1048 
1049 	p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
1050 	WRITE_BYTE(&p[PLX9054_INTCSR], PLX9054_INT_ENABLE);
1051 	DIVA_OS_MEM_DETACH_RESET(IoAdapter, p);
1052 
1053 	diva_os_wait(100);
1054 
1055 	return (0);
1056 #endif				/* SUPPORT_INTERRUPT_TEST_ON_4BRI */
1057 }
1058 
diva_4bri_clear_interrupts(diva_os_xdi_adapter_t * a)1059 static void diva_4bri_clear_interrupts(diva_os_xdi_adapter_t *a)
1060 {
1061 	PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1062 
1063 	/*
1064 	  clear any pending interrupt
1065 	*/
1066 	IoAdapter->disIrq(IoAdapter);
1067 
1068 	IoAdapter->tst_irq(&IoAdapter->a);
1069 	IoAdapter->clr_irq(&IoAdapter->a);
1070 	IoAdapter->tst_irq(&IoAdapter->a);
1071 
1072 	/*
1073 	  kill pending dpcs
1074 	*/
1075 	diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
1076 	diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
1077 }
1078 
diva_4bri_stop_adapter(diva_os_xdi_adapter_t * a)1079 static int diva_4bri_stop_adapter(diva_os_xdi_adapter_t *a)
1080 {
1081 	PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
1082 	int i;
1083 
1084 	if (!IoAdapter->ram) {
1085 		return (-1);
1086 	}
1087 
1088 	if (!IoAdapter->Initialized) {
1089 		DBG_ERR(("A: A(%d) can't stop PRI adapter - not running",
1090 			 IoAdapter->ANum))
1091 			return (-1);	/* nothing to stop */
1092 	}
1093 
1094 	for (i = 0; i < IoAdapter->tasks; i++) {
1095 		IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 0;
1096 	}
1097 
1098 	/*
1099 	  Disconnect Adapters from DIDD
1100 	*/
1101 	for (i = 0; i < IoAdapter->tasks; i++) {
1102 		diva_xdi_didd_remove_adapter(IoAdapter->QuadroList->QuadroAdapter[i]->ANum);
1103 	}
1104 
1105 	i = 100;
1106 
1107 	/*
1108 	  Stop interrupts
1109 	*/
1110 	a->clear_interrupts_proc = diva_4bri_clear_interrupts;
1111 	IoAdapter->a.ReadyInt = 1;
1112 	IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt);
1113 	do {
1114 		diva_os_sleep(10);
1115 	} while (i-- && a->clear_interrupts_proc);
1116 
1117 	if (a->clear_interrupts_proc) {
1118 		diva_4bri_clear_interrupts(a);
1119 		a->clear_interrupts_proc = NULL;
1120 		DBG_ERR(("A: A(%d) no final interrupt from 4BRI adapter",
1121 			 IoAdapter->ANum))
1122 			}
1123 	IoAdapter->a.ReadyInt = 0;
1124 
1125 	/*
1126 	  Stop and reset adapter
1127 	*/
1128 	IoAdapter->stop(IoAdapter);
1129 
1130 	return (0);
1131 }
1132