1 // SPDX-License-Identifier: GPL-2.0
2 /* $Id: os_bri.c,v 1.21 2004/03/21 17:26:01 armin Exp $ */
3 
4 #include "platform.h"
5 #include "debuglib.h"
6 #include "cardtype.h"
7 #include "pc.h"
8 #include "pr_pc.h"
9 #include "di_defs.h"
10 #include "dsp_defs.h"
11 #include "di.h"
12 #include "io.h"
13 
14 #include "xdi_msg.h"
15 #include "xdi_adapter.h"
16 #include "os_bri.h"
17 #include "diva_pci.h"
18 #include "mi_pc.h"
19 #include "pc_maint.h"
20 #include "dsrv_bri.h"
21 
22 /*
23 **  IMPORTS
24 */
25 extern void prepare_maestra_functions(PISDN_ADAPTER IoAdapter);
26 extern void diva_xdi_display_adapter_features(int card);
27 extern int diva_card_read_xlog(diva_os_xdi_adapter_t *a);
28 
29 /*
30 **  LOCALS
31 */
32 static int bri_bar_length[3] = {
33 	0x80,
34 	0x80,
35 	0x20
36 };
37 static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t *a);
38 static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t *a);
39 static int diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
40 				  diva_xdi_um_cfg_cmd_t *cmd, int length);
41 static int diva_bri_reregister_io(diva_os_xdi_adapter_t *a);
42 static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter);
43 static int diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
44 				      dword address,
45 				      const byte *data, dword length);
46 static int diva_bri_start_adapter(PISDN_ADAPTER IoAdapter,
47 				  dword start_address, dword features);
48 static int diva_bri_stop_adapter(diva_os_xdi_adapter_t *a);
49 
diva_bri_set_addresses(diva_os_xdi_adapter_t * a)50 static void diva_bri_set_addresses(diva_os_xdi_adapter_t *a)
51 {
52 	a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 0;
53 	a->resources.pci.mem_type_id[MEM_TYPE_CFG] = 1;
54 	a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2;
55 	a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 1;
56 	a->resources.pci.mem_type_id[MEM_TYPE_PORT] = 2;
57 	a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 2;
58 
59 	a->xdi_adapter.ram = a->resources.pci.addr[0];
60 	a->xdi_adapter.cfg = a->resources.pci.addr[1];
61 	a->xdi_adapter.Address = a->resources.pci.addr[2];
62 
63 	a->xdi_adapter.reset = a->xdi_adapter.cfg;
64 	a->xdi_adapter.port = a->xdi_adapter.Address;
65 
66 	a->xdi_adapter.ctlReg = a->xdi_adapter.port + M_PCI_RESET;
67 
68 	a->xdi_adapter.reset += 0x4C;	/* PLX 9050 !! */
69 }
70 
71 /*
72 **  BAR0 - MEM Addr  - 0x80  - NOT USED
73 **  BAR1 - I/O Addr  - 0x80
74 **  BAR2 - I/O Addr  - 0x20
75 */
diva_bri_init_card(diva_os_xdi_adapter_t * a)76 int diva_bri_init_card(diva_os_xdi_adapter_t *a)
77 {
78 	int bar;
79 	dword bar2 = 0, bar2_length = 0xffffffff;
80 	word cmd = 0, cmd_org;
81 	byte Bus, Slot;
82 	void *hdev;
83 	byte __iomem *p;
84 
85 	/*
86 	  Set properties
87 	*/
88 	a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
89 	DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name))
90 
91 		/*
92 		  Get resources
93 		*/
94 		for (bar = 0; bar < 3; bar++) {
95 			a->resources.pci.bar[bar] =
96 				divasa_get_pci_bar(a->resources.pci.bus,
97 						   a->resources.pci.func, bar,
98 						   a->resources.pci.hdev);
99 			if (!a->resources.pci.bar[bar]) {
100 				DBG_ERR(("A: can't get BAR[%d]", bar))
101 					return (-1);
102 			}
103 		}
104 
105 	a->resources.pci.irq =
106 		(byte) divasa_get_pci_irq(a->resources.pci.bus,
107 					  a->resources.pci.func,
108 					  a->resources.pci.hdev);
109 	if (!a->resources.pci.irq) {
110 		DBG_ERR(("A: invalid irq"));
111 		return (-1);
112 	}
113 
114 	/*
115 	  Get length of I/O bar 2 - it is different by older
116 	  EEPROM version
117 	*/
118 	Bus = a->resources.pci.bus;
119 	Slot = a->resources.pci.func;
120 	hdev = a->resources.pci.hdev;
121 
122 	/*
123 	  Get plain original values of the BAR2 CDM registers
124 	*/
125 	PCIread(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev);
126 	PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
127 	/*
128 	  Disable device and get BAR2 length
129 	*/
130 	PCIwrite(Bus, Slot, 0x04, &cmd, sizeof(cmd), hdev);
131 	PCIwrite(Bus, Slot, 0x18, &bar2_length, sizeof(bar2_length), hdev);
132 	PCIread(Bus, Slot, 0x18, &bar2_length, sizeof(bar2_length), hdev);
133 	/*
134 	  Restore BAR2 and CMD registers
135 	*/
136 	PCIwrite(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev);
137 	PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
138 
139 	/*
140 	  Calculate BAR2 length
141 	*/
142 	bar2_length = (~(bar2_length & ~7)) + 1;
143 	DBG_LOG(("BAR[2] length=%lx", bar2_length))
144 
145 		/*
146 		  Map and register resources
147 		*/
148 		if (!(a->resources.pci.addr[0] =
149 		      divasa_remap_pci_bar(a, 0, a->resources.pci.bar[0],
150 					   bri_bar_length[0]))) {
151 			DBG_ERR(("A: BRI, can't map BAR[0]"))
152 				diva_bri_cleanup_adapter(a);
153 			return (-1);
154 		}
155 
156 	sprintf(&a->port_name[0], "BRI %02x:%02x",
157 		a->resources.pci.bus, a->resources.pci.func);
158 
159 	if (diva_os_register_io_port(a, 1, a->resources.pci.bar[1],
160 				     bri_bar_length[1], &a->port_name[0], 1)) {
161 		DBG_ERR(("A: BRI, can't register BAR[1]"))
162 			diva_bri_cleanup_adapter(a);
163 		return (-1);
164 	}
165 	a->resources.pci.addr[1] = (void *) (unsigned long) a->resources.pci.bar[1];
166 	a->resources.pci.length[1] = bri_bar_length[1];
167 
168 	if (diva_os_register_io_port(a, 1, a->resources.pci.bar[2],
169 				     bar2_length, &a->port_name[0], 2)) {
170 		DBG_ERR(("A: BRI, can't register BAR[2]"))
171 			diva_bri_cleanup_adapter(a);
172 		return (-1);
173 	}
174 	a->resources.pci.addr[2] = (void *) (unsigned long) a->resources.pci.bar[2];
175 	a->resources.pci.length[2] = bar2_length;
176 
177 	/*
178 	  Set all memory areas
179 	*/
180 	diva_bri_set_addresses(a);
181 
182 	/*
183 	  Get Serial Number
184 	*/
185 	a->xdi_adapter.serialNo = diva_bri_get_serial_number(a);
186 
187 	/*
188 	  Register I/O ports with correct name now
189 	*/
190 	if (diva_bri_reregister_io(a)) {
191 		diva_bri_cleanup_adapter(a);
192 		return (-1);
193 	}
194 
195 	/*
196 	  Initialize OS dependent objects
197 	*/
198 	if (diva_os_initialize_spin_lock
199 	    (&a->xdi_adapter.isr_spin_lock, "isr")) {
200 		diva_bri_cleanup_adapter(a);
201 		return (-1);
202 	}
203 	if (diva_os_initialize_spin_lock
204 	    (&a->xdi_adapter.data_spin_lock, "data")) {
205 		diva_bri_cleanup_adapter(a);
206 		return (-1);
207 	}
208 
209 	strcpy(a->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivasbrid");
210 
211 	if (diva_os_initialize_soft_isr(&a->xdi_adapter.req_soft_isr,
212 					DIDpcRoutine, &a->xdi_adapter)) {
213 		diva_bri_cleanup_adapter(a);
214 		return (-1);
215 	}
216 	/*
217 	  Do not initialize second DPC - only one thread will be created
218 	*/
219 	a->xdi_adapter.isr_soft_isr.object = a->xdi_adapter.req_soft_isr.object;
220 
221 	/*
222 	  Create entity table
223 	*/
224 	a->xdi_adapter.Channels = CardProperties[a->CardOrdinal].Channels;
225 	a->xdi_adapter.e_max = CardProperties[a->CardOrdinal].E_info;
226 	a->xdi_adapter.e_tbl = diva_os_malloc(0, a->xdi_adapter.e_max * sizeof(E_INFO));
227 	if (!a->xdi_adapter.e_tbl) {
228 		diva_bri_cleanup_adapter(a);
229 		return (-1);
230 	}
231 	memset(a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO));
232 
233 	/*
234 	  Set up interface
235 	*/
236 	a->xdi_adapter.a.io = &a->xdi_adapter;
237 	a->xdi_adapter.DIRequest = request;
238 	a->interface.cleanup_adapter_proc = diva_bri_cleanup_adapter;
239 	a->interface.cmd_proc = diva_bri_cmd_card_proc;
240 
241 	p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter);
242 	outpp(p, 0x41);
243 	DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p);
244 
245 	prepare_maestra_functions(&a->xdi_adapter);
246 
247 	a->dsp_mask = 0x00000003;
248 
249 	/*
250 	  Set IRQ handler
251 	*/
252 	a->xdi_adapter.irq_info.irq_nr = a->resources.pci.irq;
253 	sprintf(a->xdi_adapter.irq_info.irq_name, "DIVA BRI %ld",
254 		(long) a->xdi_adapter.serialNo);
255 	if (diva_os_register_irq(a, a->xdi_adapter.irq_info.irq_nr,
256 				 a->xdi_adapter.irq_info.irq_name)) {
257 		diva_bri_cleanup_adapter(a);
258 		return (-1);
259 	}
260 	a->xdi_adapter.irq_info.registered = 1;
261 
262 	diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
263 		      a->resources.pci.irq, a->xdi_adapter.serialNo);
264 
265 	return (0);
266 }
267 
268 
diva_bri_cleanup_adapter(diva_os_xdi_adapter_t * a)269 static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t *a)
270 {
271 	int i;
272 
273 	if (a->xdi_adapter.Initialized) {
274 		diva_bri_stop_adapter(a);
275 	}
276 
277 	/*
278 	  Remove ISR Handler
279 	*/
280 	if (a->xdi_adapter.irq_info.registered) {
281 		diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
282 	}
283 	a->xdi_adapter.irq_info.registered = 0;
284 
285 	if (a->resources.pci.addr[0] && a->resources.pci.bar[0]) {
286 		divasa_unmap_pci_bar(a->resources.pci.addr[0]);
287 		a->resources.pci.addr[0] = NULL;
288 		a->resources.pci.bar[0] = 0;
289 	}
290 
291 	for (i = 1; i < 3; i++) {
292 		if (a->resources.pci.addr[i] && a->resources.pci.bar[i]) {
293 			diva_os_register_io_port(a, 0,
294 						 a->resources.pci.bar[i],
295 						 a->resources.pci.
296 						 length[i],
297 						 &a->port_name[0], i);
298 			a->resources.pci.addr[i] = NULL;
299 			a->resources.pci.bar[i] = 0;
300 		}
301 	}
302 
303 	/*
304 	  Free OS objects
305 	*/
306 	diva_os_cancel_soft_isr(&a->xdi_adapter.req_soft_isr);
307 	diva_os_cancel_soft_isr(&a->xdi_adapter.isr_soft_isr);
308 
309 	diva_os_remove_soft_isr(&a->xdi_adapter.req_soft_isr);
310 	a->xdi_adapter.isr_soft_isr.object = NULL;
311 
312 	diva_os_destroy_spin_lock(&a->xdi_adapter.isr_spin_lock, "rm");
313 	diva_os_destroy_spin_lock(&a->xdi_adapter.data_spin_lock, "rm");
314 
315 	/*
316 	  Free memory
317 	*/
318 	if (a->xdi_adapter.e_tbl) {
319 		diva_os_free(0, a->xdi_adapter.e_tbl);
320 		a->xdi_adapter.e_tbl = NULL;
321 	}
322 
323 	return (0);
324 }
325 
diva_os_prepare_maestra_functions(PISDN_ADAPTER IoAdapter)326 void diva_os_prepare_maestra_functions(PISDN_ADAPTER IoAdapter)
327 {
328 }
329 
330 /*
331 **  Get serial number
332 */
diva_bri_get_serial_number(diva_os_xdi_adapter_t * a)333 static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t *a)
334 {
335 	dword serNo = 0;
336 	byte __iomem *confIO;
337 	word serHi, serLo;
338 	word __iomem *confMem;
339 
340 	confIO = DIVA_OS_MEM_ATTACH_CFG(&a->xdi_adapter);
341 	serHi = (word) (inppw(&confIO[0x22]) & 0x0FFF);
342 	serLo = (word) (inppw(&confIO[0x26]) & 0x0FFF);
343 	serNo = ((dword) serHi << 16) | (dword) serLo;
344 	DIVA_OS_MEM_DETACH_CFG(&a->xdi_adapter, confIO);
345 
346 	if ((serNo == 0) || (serNo == 0xFFFFFFFF)) {
347 		DBG_FTL(("W: BRI use BAR[0] to get card serial number"))
348 
349 			confMem = (word __iomem *)DIVA_OS_MEM_ATTACH_RAM(&a->xdi_adapter);
350 		serHi = (word) (READ_WORD(&confMem[0x11]) & 0x0FFF);
351 		serLo = (word) (READ_WORD(&confMem[0x13]) & 0x0FFF);
352 		serNo = (((dword) serHi) << 16) | ((dword) serLo);
353 		DIVA_OS_MEM_DETACH_RAM(&a->xdi_adapter, confMem);
354 	}
355 
356 	DBG_LOG(("Serial Number=%ld", serNo))
357 
358 		return (serNo);
359 }
360 
361 /*
362 **  Unregister I/O and register it with new name,
363 **  based on Serial Number
364 */
diva_bri_reregister_io(diva_os_xdi_adapter_t * a)365 static int diva_bri_reregister_io(diva_os_xdi_adapter_t *a)
366 {
367 	int i;
368 
369 	for (i = 1; i < 3; i++) {
370 		diva_os_register_io_port(a, 0, a->resources.pci.bar[i],
371 					 a->resources.pci.length[i],
372 					 &a->port_name[0], i);
373 		a->resources.pci.addr[i] = NULL;
374 	}
375 
376 	sprintf(a->port_name, "DIVA BRI %ld",
377 		(long) a->xdi_adapter.serialNo);
378 
379 	for (i = 1; i < 3; i++) {
380 		if (diva_os_register_io_port(a, 1, a->resources.pci.bar[i],
381 					     a->resources.pci.length[i],
382 					     &a->port_name[0], i)) {
383 			DBG_ERR(("A: failed to reregister BAR[%d]", i))
384 				return (-1);
385 		}
386 		a->resources.pci.addr[i] =
387 			(void *) (unsigned long) a->resources.pci.bar[i];
388 	}
389 
390 	return (0);
391 }
392 
393 /*
394 **  Process command from user mode
395 */
396 static int
diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter * a,diva_xdi_um_cfg_cmd_t * cmd,int length)397 diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
398 		       diva_xdi_um_cfg_cmd_t *cmd, int length)
399 {
400 	int ret = -1;
401 
402 	if (cmd->adapter != a->controller) {
403 		DBG_ERR(("A: pri_cmd, invalid controller=%d != %d",
404 			 cmd->adapter, a->controller))
405 			return (-1);
406 	}
407 
408 	switch (cmd->command) {
409 	case DIVA_XDI_UM_CMD_GET_CARD_ORDINAL:
410 		a->xdi_mbox.data_length = sizeof(dword);
411 		a->xdi_mbox.data =
412 			diva_os_malloc(0, a->xdi_mbox.data_length);
413 		if (a->xdi_mbox.data) {
414 			*(dword *) a->xdi_mbox.data =
415 				(dword) a->CardOrdinal;
416 			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
417 			ret = 0;
418 		}
419 		break;
420 
421 	case DIVA_XDI_UM_CMD_GET_SERIAL_NR:
422 		a->xdi_mbox.data_length = sizeof(dword);
423 		a->xdi_mbox.data =
424 			diva_os_malloc(0, a->xdi_mbox.data_length);
425 		if (a->xdi_mbox.data) {
426 			*(dword *) a->xdi_mbox.data =
427 				(dword) a->xdi_adapter.serialNo;
428 			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
429 			ret = 0;
430 		}
431 		break;
432 
433 	case DIVA_XDI_UM_CMD_GET_PCI_HW_CONFIG:
434 		a->xdi_mbox.data_length = sizeof(dword) * 9;
435 		a->xdi_mbox.data =
436 			diva_os_malloc(0, a->xdi_mbox.data_length);
437 		if (a->xdi_mbox.data) {
438 			int i;
439 			dword *data = (dword *) a->xdi_mbox.data;
440 
441 			for (i = 0; i < 8; i++) {
442 				*data++ = a->resources.pci.bar[i];
443 			}
444 			*data++ = (dword) a->resources.pci.irq;
445 			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
446 			ret = 0;
447 		}
448 		break;
449 
450 	case DIVA_XDI_UM_CMD_GET_CARD_STATE:
451 		a->xdi_mbox.data_length = sizeof(dword);
452 		a->xdi_mbox.data =
453 			diva_os_malloc(0, a->xdi_mbox.data_length);
454 		if (a->xdi_mbox.data) {
455 			dword *data = (dword *) a->xdi_mbox.data;
456 			if (!a->xdi_adapter.port) {
457 				*data = 3;
458 			} else if (a->xdi_adapter.trapped) {
459 				*data = 2;
460 			} else if (a->xdi_adapter.Initialized) {
461 				*data = 1;
462 			} else {
463 				*data = 0;
464 			}
465 			a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
466 			ret = 0;
467 		}
468 		break;
469 
470 	case DIVA_XDI_UM_CMD_RESET_ADAPTER:
471 		ret = diva_bri_reset_adapter(&a->xdi_adapter);
472 		break;
473 
474 	case DIVA_XDI_UM_CMD_WRITE_SDRAM_BLOCK:
475 		ret = diva_bri_write_sdram_block(&a->xdi_adapter,
476 						 cmd->command_data.
477 						 write_sdram.offset,
478 						 (byte *)&cmd[1],
479 						 cmd->command_data.
480 						 write_sdram.length);
481 		break;
482 
483 	case DIVA_XDI_UM_CMD_START_ADAPTER:
484 		ret = diva_bri_start_adapter(&a->xdi_adapter,
485 					     cmd->command_data.start.
486 					     offset,
487 					     cmd->command_data.start.
488 					     features);
489 		break;
490 
491 	case DIVA_XDI_UM_CMD_SET_PROTOCOL_FEATURES:
492 		a->xdi_adapter.features =
493 			cmd->command_data.features.features;
494 		a->xdi_adapter.a.protocol_capabilities =
495 			a->xdi_adapter.features;
496 		DBG_TRC(
497 			("Set raw protocol features (%08x)",
498 			 a->xdi_adapter.features)) ret = 0;
499 		break;
500 
501 	case DIVA_XDI_UM_CMD_STOP_ADAPTER:
502 		ret = diva_bri_stop_adapter(a);
503 		break;
504 
505 	case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
506 		ret = diva_card_read_xlog(a);
507 		break;
508 
509 	default:
510 		DBG_ERR(
511 			("A: A(%d) invalid cmd=%d", a->controller,
512 			 cmd->command))}
513 
514 	return (ret);
515 }
516 
diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter)517 static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter)
518 {
519 	byte __iomem *addrHi, *addrLo, *ioaddr;
520 	dword i;
521 	byte __iomem *Port;
522 
523 	if (!IoAdapter->port) {
524 		return (-1);
525 	}
526 	if (IoAdapter->Initialized) {
527 		DBG_ERR(("A: A(%d) can't reset BRI adapter - please stop first",
528 			 IoAdapter->ANum)) return (-1);
529 	}
530 	(*(IoAdapter->rstFnc)) (IoAdapter);
531 	diva_os_wait(100);
532 	Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter);
533 	addrHi = Port +
534 		((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
535 	addrLo = Port + ADDR;
536 	ioaddr = Port + DATA;
537 	/*
538 	  recover
539 	*/
540 	outpp(addrHi, (byte) 0);
541 	outppw(addrLo, (word) 0);
542 	outppw(ioaddr, (word) 0);
543 	/*
544 	  clear shared memory
545 	*/
546 	outpp(addrHi,
547 	      (byte) (
548 		      (IoAdapter->MemoryBase + IoAdapter->MemorySize -
549 		       BRI_SHARED_RAM_SIZE) >> 16));
550 	outppw(addrLo, 0);
551 	for (i = 0; i < 0x8000; outppw(ioaddr, 0), ++i);
552 	diva_os_wait(100);
553 
554 	/*
555 	  clear signature
556 	*/
557 	outpp(addrHi,
558 	      (byte) (
559 		      (IoAdapter->MemoryBase + IoAdapter->MemorySize -
560 		       BRI_SHARED_RAM_SIZE) >> 16));
561 	outppw(addrLo, 0x1e);
562 	outpp(ioaddr, 0);
563 	outpp(ioaddr, 0);
564 
565 	outpp(addrHi, (byte) 0);
566 	outppw(addrLo, (word) 0);
567 	outppw(ioaddr, (word) 0);
568 
569 	DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port);
570 
571 	/*
572 	  Forget all outstanding entities
573 	*/
574 	IoAdapter->e_count = 0;
575 	if (IoAdapter->e_tbl) {
576 		memset(IoAdapter->e_tbl, 0x00,
577 		       IoAdapter->e_max * sizeof(E_INFO));
578 	}
579 	IoAdapter->head = 0;
580 	IoAdapter->tail = 0;
581 	IoAdapter->assign = 0;
582 	IoAdapter->trapped = 0;
583 
584 	memset(&IoAdapter->a.IdTable[0], 0x00,
585 	       sizeof(IoAdapter->a.IdTable));
586 	memset(&IoAdapter->a.IdTypeTable[0], 0x00,
587 	       sizeof(IoAdapter->a.IdTypeTable));
588 	memset(&IoAdapter->a.FlowControlIdTable[0], 0x00,
589 	       sizeof(IoAdapter->a.FlowControlIdTable));
590 	memset(&IoAdapter->a.FlowControlSkipTable[0], 0x00,
591 	       sizeof(IoAdapter->a.FlowControlSkipTable));
592 	memset(&IoAdapter->a.misc_flags_table[0], 0x00,
593 	       sizeof(IoAdapter->a.misc_flags_table));
594 	memset(&IoAdapter->a.rx_stream[0], 0x00,
595 	       sizeof(IoAdapter->a.rx_stream));
596 	memset(&IoAdapter->a.tx_stream[0], 0x00,
597 	       sizeof(IoAdapter->a.tx_stream));
598 	memset(&IoAdapter->a.tx_pos[0], 0x00, sizeof(IoAdapter->a.tx_pos));
599 	memset(&IoAdapter->a.rx_pos[0], 0x00, sizeof(IoAdapter->a.rx_pos));
600 
601 	return (0);
602 }
603 
604 static int
diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter,dword address,const byte * data,dword length)605 diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
606 			   dword address, const byte *data, dword length)
607 {
608 	byte __iomem *addrHi, *addrLo, *ioaddr;
609 	byte __iomem *Port;
610 
611 	if (!IoAdapter->port) {
612 		return (-1);
613 	}
614 
615 	Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter);
616 	addrHi = Port +
617 		((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
618 	addrLo = Port + ADDR;
619 	ioaddr = Port + DATA;
620 
621 	while (length--) {
622 		outpp(addrHi, (word) (address >> 16));
623 		outppw(addrLo, (word) (address & 0x0000ffff));
624 		outpp(ioaddr, *data++);
625 		address++;
626 	}
627 
628 	DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port);
629 	return (0);
630 }
631 
632 static int
diva_bri_start_adapter(PISDN_ADAPTER IoAdapter,dword start_address,dword features)633 diva_bri_start_adapter(PISDN_ADAPTER IoAdapter,
634 		       dword start_address, dword features)
635 {
636 	byte __iomem *Port;
637 	dword i, test;
638 	byte __iomem *addrHi, *addrLo, *ioaddr;
639 	int started = 0;
640 	ADAPTER *a = &IoAdapter->a;
641 
642 	if (IoAdapter->Initialized) {
643 		DBG_ERR(
644 			("A: A(%d) bri_start_adapter, adapter already running",
645 			 IoAdapter->ANum)) return (-1);
646 	}
647 	if (!IoAdapter->port) {
648 		DBG_ERR(("A: A(%d) bri_start_adapter, adapter not mapped",
649 			 IoAdapter->ANum)) return (-1);
650 	}
651 
652 	sprintf(IoAdapter->Name, "A(%d)", (int) IoAdapter->ANum);
653 	DBG_LOG(("A(%d) start BRI", IoAdapter->ANum))
654 
655 		Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter);
656 	addrHi = Port +
657 		((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
658 	addrLo = Port + ADDR;
659 	ioaddr = Port + DATA;
660 
661 	outpp(addrHi,
662 	      (byte) (
663 		      (IoAdapter->MemoryBase + IoAdapter->MemorySize -
664 		       BRI_SHARED_RAM_SIZE) >> 16));
665 	outppw(addrLo, 0x1e);
666 	outppw(ioaddr, 0x00);
667 	DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port);
668 
669 	/*
670 	  start the protocol code
671 	*/
672 	Port = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
673 	outpp(Port, 0x08);
674 	DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, Port);
675 
676 	Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter);
677 	addrHi = Port +
678 		((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
679 	addrLo = Port + ADDR;
680 	ioaddr = Port + DATA;
681 	/*
682 	  wait for signature (max. 3 seconds)
683 	*/
684 	for (i = 0; i < 300; ++i) {
685 		diva_os_wait(10);
686 		outpp(addrHi,
687 		      (byte) (
688 			      (IoAdapter->MemoryBase +
689 			       IoAdapter->MemorySize -
690 			       BRI_SHARED_RAM_SIZE) >> 16));
691 		outppw(addrLo, 0x1e);
692 		test = (dword) inppw(ioaddr);
693 		if (test == 0x4447) {
694 			DBG_LOG(
695 				("Protocol startup time %d.%02d seconds",
696 				 (i / 100), (i % 100)))
697 				started = 1;
698 			break;
699 		}
700 	}
701 	DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port);
702 
703 	if (!started) {
704 		DBG_FTL(("A: A(%d) %s: Adapter selftest failed 0x%04X",
705 			 IoAdapter->ANum, IoAdapter->Properties.Name,
706 			 test))
707 			(*(IoAdapter->trapFnc)) (IoAdapter);
708 		return (-1);
709 	}
710 
711 	IoAdapter->Initialized = 1;
712 
713 	/*
714 	  Check Interrupt
715 	*/
716 	IoAdapter->IrqCount = 0;
717 	a->ReadyInt = 1;
718 
719 	if (IoAdapter->reset) {
720 		Port = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
721 		outpp(Port, 0x41);
722 		DIVA_OS_MEM_DETACH_RESET(IoAdapter, Port);
723 	}
724 
725 	a->ram_out(a, &PR_RAM->ReadyInt, 1);
726 	for (i = 0; ((!IoAdapter->IrqCount) && (i < 100)); i++) {
727 		diva_os_wait(10);
728 	}
729 	if (!IoAdapter->IrqCount) {
730 		DBG_ERR(
731 			("A: A(%d) interrupt test failed",
732 			 IoAdapter->ANum))
733 			IoAdapter->Initialized = 0;
734 		IoAdapter->stop(IoAdapter);
735 		return (-1);
736 	}
737 
738 	IoAdapter->Properties.Features = (word) features;
739 	diva_xdi_display_adapter_features(IoAdapter->ANum);
740 	DBG_LOG(("A(%d) BRI adapter successfully started", IoAdapter->ANum))
741 		/*
742 		  Register with DIDD
743 		*/
744 		diva_xdi_didd_register_adapter(IoAdapter->ANum);
745 
746 	return (0);
747 }
748 
diva_bri_clear_interrupts(diva_os_xdi_adapter_t * a)749 static void diva_bri_clear_interrupts(diva_os_xdi_adapter_t *a)
750 {
751 	PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
752 
753 	/*
754 	  clear any pending interrupt
755 	*/
756 	IoAdapter->disIrq(IoAdapter);
757 
758 	IoAdapter->tst_irq(&IoAdapter->a);
759 	IoAdapter->clr_irq(&IoAdapter->a);
760 	IoAdapter->tst_irq(&IoAdapter->a);
761 
762 	/*
763 	  kill pending dpcs
764 	*/
765 	diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
766 	diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
767 }
768 
769 /*
770 **  Stop card
771 */
diva_bri_stop_adapter(diva_os_xdi_adapter_t * a)772 static int diva_bri_stop_adapter(diva_os_xdi_adapter_t *a)
773 {
774 	PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
775 	int i = 100;
776 
777 	if (!IoAdapter->port) {
778 		return (-1);
779 	}
780 	if (!IoAdapter->Initialized) {
781 		DBG_ERR(("A: A(%d) can't stop BRI adapter - not running",
782 			 IoAdapter->ANum))
783 			return (-1);	/* nothing to stop */
784 	}
785 	IoAdapter->Initialized = 0;
786 
787 	/*
788 	  Disconnect Adapter from DIDD
789 	*/
790 	diva_xdi_didd_remove_adapter(IoAdapter->ANum);
791 
792 	/*
793 	  Stop interrupts
794 	*/
795 	a->clear_interrupts_proc = diva_bri_clear_interrupts;
796 	IoAdapter->a.ReadyInt = 1;
797 	IoAdapter->a.ram_inc(&IoAdapter->a, &PR_RAM->ReadyInt);
798 	do {
799 		diva_os_sleep(10);
800 	} while (i-- && a->clear_interrupts_proc);
801 	if (a->clear_interrupts_proc) {
802 		diva_bri_clear_interrupts(a);
803 		a->clear_interrupts_proc = NULL;
804 		DBG_ERR(("A: A(%d) no final interrupt from BRI adapter",
805 			 IoAdapter->ANum))
806 			}
807 	IoAdapter->a.ReadyInt = 0;
808 
809 	/*
810 	  Stop and reset adapter
811 	*/
812 	IoAdapter->stop(IoAdapter);
813 
814 	return (0);
815 }
816