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