]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blob - drivers/isdn/hardware/eicon/os_bri.c
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[mirror_ubuntu-kernels.git] / drivers / isdn / hardware / eicon / os_bri.c
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
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 */
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
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
326 void diva_os_prepare_maestra_functions(PISDN_ADAPTER IoAdapter)
327 {
328 }
329
330 /*
331 ** Get serial number
332 */
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 */
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
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
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
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
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
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 */
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 }