[XFRM]: skb_cow_data() does not set proper owner for new skbs.
[linux-2.6/verdex.git] / drivers / isdn / hardware / eicon / os_bri.c
blob4cc44a5dd1dbe63aa39881b217f5b2c72c5d8db8
1 /* $Id: os_bri.c,v 1.21 2004/03/21 17:26:01 armin Exp $ */
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"
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"
21 ** IMPORTS
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);
28 ** LOCALS
30 static int bri_bar_length[3] = {
31 0x80,
32 0x80,
33 0x20
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);
48 static void diva_bri_set_addresses(diva_os_xdi_adapter_t * a)
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;
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];
61 a->xdi_adapter.reset = a->xdi_adapter.cfg;
62 a->xdi_adapter.port = a->xdi_adapter.Address;
64 a->xdi_adapter.ctlReg = a->xdi_adapter.port + M_PCI_RESET;
66 a->xdi_adapter.reset += 0x4C; /* PLX 9050 !! */
70 ** BAR0 - MEM Addr - 0x80 - NOT USED
71 ** BAR1 - I/O Addr - 0x80
72 ** BAR2 - I/O Addr - 0x20
74 int diva_bri_init_card(diva_os_xdi_adapter_t * a)
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;
84 Set properties
86 a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
87 DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name))
90 Get resources
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);
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);
113 Get length of I/O bar 2 - it is different by older
114 EEPROM version
116 Bus = a->resources.pci.bus;
117 Slot = a->resources.pci.func;
118 hdev = a->resources.pci.hdev;
121 Get plain original values of the BAR2 CDM registers
123 PCIread(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev);
124 PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
126 Disable device and get BAR2 length
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);
132 Restore BAR2 and CMD registers
134 PCIwrite(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev);
135 PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
138 Calculate BAR2 length
140 bar2_length = (~(bar2_length & ~7)) + 1;
141 DBG_LOG(("BAR[2] length=%lx", bar2_length))
144 Map and register resources
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);
154 sprintf(&a->port_name[0], "BRI %02x:%02x",
155 a->resources.pci.bus, a->resources.pci.func);
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);
163 a->resources.pci.addr[1] = (void *) (unsigned long) a->resources.pci.bar[1];
164 a->resources.pci.length[1] = bri_bar_length[1];
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);
172 a->resources.pci.addr[2] = (void *) (unsigned long) a->resources.pci.bar[2];
173 a->resources.pci.length[2] = bar2_length;
176 Set all memory areas
178 diva_bri_set_addresses(a);
181 Get Serial Number
183 a->xdi_adapter.serialNo = diva_bri_get_serial_number(a);
186 Register I/O ports with correct name now
188 if (diva_bri_reregister_io(a)) {
189 diva_bri_cleanup_adapter(a);
190 return (-1);
194 Initialize OS dependent objects
196 if (diva_os_initialize_spin_lock
197 (&a->xdi_adapter.isr_spin_lock, "isr")) {
198 diva_bri_cleanup_adapter(a);
199 return (-1);
201 if (diva_os_initialize_spin_lock
202 (&a->xdi_adapter.data_spin_lock, "data")) {
203 diva_bri_cleanup_adapter(a);
204 return (-1);
207 strcpy(a->xdi_adapter.req_soft_isr.dpc_thread_name, "kdivasbrid");
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);
215 Do not initialize second DPC - only one thread will be created
217 a->xdi_adapter.isr_soft_isr.object = a->xdi_adapter.req_soft_isr.object;
220 Create entity table
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);
229 memset(a->xdi_adapter.e_tbl, 0x00, a->xdi_adapter.e_max * sizeof(E_INFO));
232 Set up interface
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;
239 p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter);
240 outpp(p, 0x41);
241 DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p);
243 prepare_maestra_functions(&a->xdi_adapter);
245 a->dsp_mask = 0x00000003;
248 Set IRQ handler
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);
258 a->xdi_adapter.irq_info.registered = 1;
260 diva_log_info("%s IRQ:%d SerNo:%d", a->xdi_adapter.Properties.Name,
261 a->resources.pci.irq, a->xdi_adapter.serialNo);
263 return (0);
267 static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t * a)
269 int i;
271 if (a->xdi_adapter.Initialized) {
272 diva_bri_stop_adapter(a);
276 Remove ISR Handler
278 if (a->xdi_adapter.irq_info.registered) {
279 diva_os_remove_irq(a, a->xdi_adapter.irq_info.irq_nr);
281 a->xdi_adapter.irq_info.registered = 0;
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;
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;
302 Free OS objects
304 diva_os_cancel_soft_isr(&a->xdi_adapter.req_soft_isr);
305 diva_os_cancel_soft_isr(&a->xdi_adapter.isr_soft_isr);
307 diva_os_remove_soft_isr(&a->xdi_adapter.req_soft_isr);
308 a->xdi_adapter.isr_soft_isr.object = NULL;
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");
314 Free memory
316 if (a->xdi_adapter.e_tbl) {
317 diva_os_free(0, a->xdi_adapter.e_tbl);
318 a->xdi_adapter.e_tbl = NULL;
321 return (0);
324 void diva_os_prepare_maestra_functions(PISDN_ADAPTER IoAdapter)
329 ** Get serial number
331 static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t * a)
333 dword serNo = 0;
334 byte __iomem *confIO;
335 word serHi, serLo;
336 word __iomem *confMem;
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);
344 if ((serNo == 0) || (serNo == 0xFFFFFFFF)) {
345 DBG_FTL(("W: BRI use BAR[0] to get card serial number"))
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);
354 DBG_LOG(("Serial Number=%ld", serNo))
356 return (serNo);
360 ** Unregister I/O and register it with new name,
361 ** based on Serial Number
363 static int diva_bri_reregister_io(diva_os_xdi_adapter_t * a)
365 int i;
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;
374 sprintf(a->port_name, "DIVA BRI %ld",
375 (long) a->xdi_adapter.serialNo);
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);
384 a->resources.pci.addr[i] =
385 (void *) (unsigned long) a->resources.pci.bar[i];
388 return (0);
392 ** Process command from user mode
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)
398 int ret = -1;
400 if (cmd->adapter != a->controller) {
401 DBG_ERR(("A: pri_cmd, invalid controller=%d != %d",
402 cmd->adapter, a->controller))
403 return (-1);
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;
417 break;
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;
429 break;
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;
439 for (i = 0; i < 8; i++) {
440 *data++ = a->resources.pci.bar[i];
442 *data++ = (dword) a->resources.pci.irq;
443 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
444 ret = 0;
446 break;
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;
463 a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
464 ret = 0;
466 break;
468 case DIVA_XDI_UM_CMD_RESET_ADAPTER:
469 ret = diva_bri_reset_adapter(&a->xdi_adapter);
470 break;
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;
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;
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;
499 case DIVA_XDI_UM_CMD_STOP_ADAPTER:
500 ret = diva_bri_stop_adapter(a);
501 break;
503 case DIVA_XDI_UM_CMD_READ_XLOG_ENTRY:
504 ret = diva_card_read_xlog(a);
505 break;
507 default:
508 DBG_ERR(
509 ("A: A(%d) invalid cmd=%d", a->controller,
510 cmd->command))}
512 return (ret);
515 static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter)
517 byte __iomem *addrHi, *addrLo, *ioaddr;
518 dword i;
519 byte __iomem *Port;
521 if (!IoAdapter->port) {
522 return (-1);
524 if (IoAdapter->Initialized) {
525 DBG_ERR(("A: A(%d) can't reset BRI adapter - please stop first",
526 IoAdapter->ANum)) return (-1);
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;
536 recover
538 outpp(addrHi, (byte) 0);
539 outppw(addrLo, (word) 0);
540 outppw(ioaddr, (word) 0);
542 clear shared memory
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);
553 clear signature
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);
563 outpp(addrHi, (byte) 0);
564 outppw(addrLo, (word) 0);
565 outppw(ioaddr, (word) 0);
567 DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port);
570 Forget all outstanding entities
572 IoAdapter->e_count = 0;
573 if (IoAdapter->e_tbl) {
574 memset(IoAdapter->e_tbl, 0x00,
575 IoAdapter->e_max * sizeof(E_INFO));
577 IoAdapter->head = 0;
578 IoAdapter->tail = 0;
579 IoAdapter->assign = 0;
580 IoAdapter->trapped = 0;
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));
599 return (0);
602 static int
603 diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
604 dword address, const byte * data, dword length)
606 byte __iomem *addrHi, *addrLo, *ioaddr;
607 byte __iomem *Port;
609 if (!IoAdapter->port) {
610 return (-1);
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;
619 while (length--) {
620 outpp(addrHi, (word) (address >> 16));
621 outppw(addrLo, (word) (address & 0x0000ffff));
622 outpp(ioaddr, *data++);
623 address++;
626 DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port);
627 return (0);
630 static int
631 diva_bri_start_adapter(PISDN_ADAPTER IoAdapter,
632 dword start_address, dword features)
634 byte __iomem *Port;
635 dword i, test;
636 byte __iomem *addrHi, *addrLo, *ioaddr;
637 int started = 0;
638 ADAPTER *a = &IoAdapter->a;
640 if (IoAdapter->Initialized) {
641 DBG_ERR(
642 ("A: A(%d) bri_start_adapter, adapter already running",
643 IoAdapter->ANum)) return (-1);
645 if (!IoAdapter->port) {
646 DBG_ERR(("A: A(%d) bri_start_adapter, adapter not mapped",
647 IoAdapter->ANum)) return (-1);
650 sprintf(IoAdapter->Name, "A(%d)", (int) IoAdapter->ANum);
651 DBG_LOG(("A(%d) start BRI", IoAdapter->ANum))
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;
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);
668 start the protocol code
670 Port = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter);
671 outpp(Port, 0x08);
672 DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, Port);
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;
680 wait for signature (max. 3 seconds)
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;
699 DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port);
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);
709 IoAdapter->Initialized = 1;
712 Check Interrupt
714 IoAdapter->IrqCount = 0;
715 a->ReadyInt = 1;
717 if (IoAdapter->reset) {
718 Port = DIVA_OS_MEM_ATTACH_RESET(IoAdapter);
719 outpp(Port, 0x41);
720 DIVA_OS_MEM_DETACH_RESET(IoAdapter, Port);
723 a->ram_out(a, &PR_RAM->ReadyInt, 1);
724 for (i = 0; ((!IoAdapter->IrqCount) && (i < 100)); i++) {
725 diva_os_wait(10);
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);
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))
740 Register with DIDD
742 diva_xdi_didd_register_adapter(IoAdapter->ANum);
744 return (0);
747 static void diva_bri_clear_interrupts(diva_os_xdi_adapter_t * a)
749 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
752 clear any pending interrupt
754 IoAdapter->disIrq(IoAdapter);
756 IoAdapter->tst_irq(&IoAdapter->a);
757 IoAdapter->clr_irq(&IoAdapter->a);
758 IoAdapter->tst_irq(&IoAdapter->a);
761 kill pending dpcs
763 diva_os_cancel_soft_isr(&IoAdapter->req_soft_isr);
764 diva_os_cancel_soft_isr(&IoAdapter->isr_soft_isr);
768 ** Stop card
770 static int diva_bri_stop_adapter(diva_os_xdi_adapter_t * a)
772 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
773 int i = 100;
775 if (!IoAdapter->port) {
776 return (-1);
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 */
783 IoAdapter->Initialized = 0;
786 Disconnect Adapter from DIDD
788 diva_xdi_didd_remove_adapter(IoAdapter->ANum);
791 Stop interrupts
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))
805 IoAdapter->a.ReadyInt = 0;
808 Stop and reset adapter
810 IoAdapter->stop(IoAdapter);
812 return (0);