]> git.ipfire.org Git - thirdparty/kernel/linux.git/blame - drivers/isdn/hardware/eicon/os_bri.c
License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[thirdparty/kernel/linux.git] / drivers / isdn / hardware / eicon / os_bri.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
1da177e4
LT
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"
6e21bd9a 20#include "dsrv_bri.h"
1da177e4
LT
21
22/*
23** IMPORTS
24*/
25extern void prepare_maestra_functions(PISDN_ADAPTER IoAdapter);
26extern void diva_xdi_display_adapter_features(int card);
475be4d8 27extern int diva_card_read_xlog(diva_os_xdi_adapter_t *a);
1da177e4
LT
28
29/*
30** LOCALS
31*/
32static int bri_bar_length[3] = {
33 0x80,
34 0x80,
35 0x20
36};
475be4d8
JP
37static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t *a);
38static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t *a);
1da177e4 39static int diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
475be4d8
JP
40 diva_xdi_um_cfg_cmd_t *cmd, int length);
41static int diva_bri_reregister_io(diva_os_xdi_adapter_t *a);
1da177e4
LT
42static int diva_bri_reset_adapter(PISDN_ADAPTER IoAdapter);
43static int diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
44 dword address,
475be4d8 45 const byte *data, dword length);
1da177e4
LT
46static int diva_bri_start_adapter(PISDN_ADAPTER IoAdapter,
47 dword start_address, dword features);
475be4d8 48static int diva_bri_stop_adapter(diva_os_xdi_adapter_t *a);
1da177e4 49
475be4d8 50static void diva_bri_set_addresses(diva_os_xdi_adapter_t *a)
1da177e4
LT
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;
475be4d8 58
1da177e4
LT
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*/
475be4d8 76int diva_bri_init_card(diva_os_xdi_adapter_t *a)
1da177e4
LT
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 /*
475be4d8
JP
86 Set properties
87 */
1da177e4
LT
88 a->xdi_adapter.Properties = CardProperties[a->CardOrdinal];
89 DBG_LOG(("Load %s", a->xdi_adapter.Properties.Name))
90
475be4d8
JP
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 }
1da177e4 103 }
1da177e4
LT
104
105 a->resources.pci.irq =
475be4d8
JP
106 (byte) divasa_get_pci_irq(a->resources.pci.bus,
107 a->resources.pci.func,
108 a->resources.pci.hdev);
1da177e4
LT
109 if (!a->resources.pci.irq) {
110 DBG_ERR(("A: invalid irq"));
111 return (-1);
112 }
113
114 /*
475be4d8
JP
115 Get length of I/O bar 2 - it is different by older
116 EEPROM version
117 */
1da177e4
LT
118 Bus = a->resources.pci.bus;
119 Slot = a->resources.pci.func;
120 hdev = a->resources.pci.hdev;
121
122 /*
475be4d8
JP
123 Get plain original values of the BAR2 CDM registers
124 */
1da177e4
LT
125 PCIread(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev);
126 PCIread(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
127 /*
475be4d8
JP
128 Disable device and get BAR2 length
129 */
1da177e4
LT
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 /*
475be4d8
JP
134 Restore BAR2 and CMD registers
135 */
1da177e4
LT
136 PCIwrite(Bus, Slot, 0x18, &bar2, sizeof(bar2), hdev);
137 PCIwrite(Bus, Slot, 0x04, &cmd_org, sizeof(cmd_org), hdev);
138
139 /*
475be4d8
JP
140 Calculate BAR2 length
141 */
1da177e4
LT
142 bar2_length = (~(bar2_length & ~7)) + 1;
143 DBG_LOG(("BAR[2] length=%lx", bar2_length))
144
475be4d8
JP
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 }
1da177e4
LT
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]"))
475be4d8 162 diva_bri_cleanup_adapter(a);
1da177e4
LT
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]"))
475be4d8 171 diva_bri_cleanup_adapter(a);
1da177e4
LT
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 /*
475be4d8
JP
178 Set all memory areas
179 */
1da177e4
LT
180 diva_bri_set_addresses(a);
181
182 /*
475be4d8
JP
183 Get Serial Number
184 */
1da177e4
LT
185 a->xdi_adapter.serialNo = diva_bri_get_serial_number(a);
186
187 /*
475be4d8
JP
188 Register I/O ports with correct name now
189 */
1da177e4
LT
190 if (diva_bri_reregister_io(a)) {
191 diva_bri_cleanup_adapter(a);
192 return (-1);
193 }
194
195 /*
475be4d8
JP
196 Initialize OS dependent objects
197 */
1da177e4
LT
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 /*
475be4d8
JP
217 Do not initialize second DPC - only one thread will be created
218 */
1da177e4
LT
219 a->xdi_adapter.isr_soft_isr.object = a->xdi_adapter.req_soft_isr.object;
220
221 /*
475be4d8
JP
222 Create entity table
223 */
1da177e4
LT
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 /*
475be4d8
JP
234 Set up interface
235 */
1da177e4
LT
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 /*
475be4d8
JP
250 Set IRQ handler
251 */
1da177e4
LT
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
475be4d8 269static int diva_bri_cleanup_adapter(diva_os_xdi_adapter_t *a)
1da177e4
LT
270{
271 int i;
272
273 if (a->xdi_adapter.Initialized) {
274 diva_bri_stop_adapter(a);
275 }
276
277 /*
475be4d8
JP
278 Remove ISR Handler
279 */
1da177e4
LT
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 /*
475be4d8
JP
304 Free OS objects
305 */
1da177e4
LT
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 /*
475be4d8
JP
316 Free memory
317 */
1da177e4
LT
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
326void diva_os_prepare_maestra_functions(PISDN_ADAPTER IoAdapter)
327{
328}
329
330/*
331** Get serial number
332*/
475be4d8 333static dword diva_bri_get_serial_number(diva_os_xdi_adapter_t *a)
1da177e4
LT
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
475be4d8 349 confMem = (word __iomem *)DIVA_OS_MEM_ATTACH_RAM(&a->xdi_adapter);
1da177e4
LT
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
475be4d8 358 return (serNo);
1da177e4
LT
359}
360
361/*
362** Unregister I/O and register it with new name,
363** based on Serial Number
364*/
475be4d8 365static int diva_bri_reregister_io(diva_os_xdi_adapter_t *a)
1da177e4
LT
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))
475be4d8 384 return (-1);
1da177e4
LT
385 }
386 a->resources.pci.addr[i] =
475be4d8 387 (void *) (unsigned long) a->resources.pci.bar[i];
1da177e4
LT
388 }
389
390 return (0);
391}
392
393/*
394** Process command from user mode
395*/
396static int
397diva_bri_cmd_card_proc(struct _diva_os_xdi_adapter *a,
475be4d8 398 diva_xdi_um_cfg_cmd_t *cmd, int length)
1da177e4
LT
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))
475be4d8 405 return (-1);
1da177e4
LT
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 =
475be4d8 412 diva_os_malloc(0, a->xdi_mbox.data_length);
1da177e4
LT
413 if (a->xdi_mbox.data) {
414 *(dword *) a->xdi_mbox.data =
475be4d8 415 (dword) a->CardOrdinal;
1da177e4
LT
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 =
475be4d8 424 diva_os_malloc(0, a->xdi_mbox.data_length);
1da177e4
LT
425 if (a->xdi_mbox.data) {
426 *(dword *) a->xdi_mbox.data =
475be4d8 427 (dword) a->xdi_adapter.serialNo;
1da177e4
LT
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 =
475be4d8 436 diva_os_malloc(0, a->xdi_mbox.data_length);
1da177e4
LT
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 =
475be4d8 453 diva_os_malloc(0, a->xdi_mbox.data_length);
1da177e4
LT
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,
475be4d8 478 (byte *)&cmd[1],
1da177e4
LT
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 =
475be4d8 493 cmd->command_data.features.features;
1da177e4 494 a->xdi_adapter.a.protocol_capabilities =
475be4d8 495 a->xdi_adapter.features;
1da177e4
LT
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
517static 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 +
475be4d8 534 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
1da177e4
LT
535 addrLo = Port + ADDR;
536 ioaddr = Port + DATA;
537 /*
475be4d8
JP
538 recover
539 */
1da177e4
LT
540 outpp(addrHi, (byte) 0);
541 outppw(addrLo, (word) 0);
542 outppw(ioaddr, (word) 0);
543 /*
475be4d8
JP
544 clear shared memory
545 */
1da177e4
LT
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 /*
475be4d8
JP
555 clear signature
556 */
1da177e4
LT
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 /*
475be4d8
JP
572 Forget all outstanding entities
573 */
1da177e4
LT
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
604static int
605diva_bri_write_sdram_block(PISDN_ADAPTER IoAdapter,
475be4d8 606 dword address, const byte *data, dword length)
1da177e4
LT
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 +
475be4d8 617 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
1da177e4
LT
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
632static int
633diva_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
475be4d8 655 Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter);
1da177e4 656 addrHi = Port +
475be4d8 657 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
1da177e4
LT
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 /*
475be4d8
JP
670 start the protocol code
671 */
1da177e4
LT
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 +
475be4d8 678 ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH);
1da177e4
LT
679 addrLo = Port + ADDR;
680 ioaddr = Port + DATA;
681 /*
475be4d8
JP
682 wait for signature (max. 3 seconds)
683 */
1da177e4
LT
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)))
475be4d8 697 started = 1;
1da177e4
LT
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))
475be4d8 707 (*(IoAdapter->trapFnc)) (IoAdapter);
1da177e4
LT
708 return (-1);
709 }
710
711 IoAdapter->Initialized = 1;
712
713 /*
475be4d8
JP
714 Check Interrupt
715 */
1da177e4
LT
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))
475be4d8 733 IoAdapter->Initialized = 0;
1da177e4
LT
734 IoAdapter->stop(IoAdapter);
735 return (-1);
736 }
737
738 IoAdapter->Properties.Features = (word) features;
739 diva_xdi_display_adapter_features(IoAdapter->ANum);
73ac36ea 740 DBG_LOG(("A(%d) BRI adapter successfully started", IoAdapter->ANum))
475be4d8
JP
741 /*
742 Register with DIDD
743 */
744 diva_xdi_didd_register_adapter(IoAdapter->ANum);
1da177e4
LT
745
746 return (0);
747}
748
475be4d8 749static void diva_bri_clear_interrupts(diva_os_xdi_adapter_t *a)
1da177e4
LT
750{
751 PISDN_ADAPTER IoAdapter = &a->xdi_adapter;
752
753 /*
475be4d8
JP
754 clear any pending interrupt
755 */
1da177e4
LT
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 /*
475be4d8
JP
763 kill pending dpcs
764 */
1da177e4
LT
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*/
475be4d8 772static int diva_bri_stop_adapter(diva_os_xdi_adapter_t *a)
1da177e4
LT
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))
475be4d8 783 return (-1); /* nothing to stop */
1da177e4
LT
784 }
785 IoAdapter->Initialized = 0;
786
787 /*
475be4d8
JP
788 Disconnect Adapter from DIDD
789 */
1da177e4
LT
790 diva_xdi_didd_remove_adapter(IoAdapter->ANum);
791
792 /*
475be4d8
JP
793 Stop interrupts
794 */
1da177e4
LT
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))
475be4d8 806 }
1da177e4
LT
807 IoAdapter->a.ReadyInt = 0;
808
809 /*
475be4d8
JP
810 Stop and reset adapter
811 */
1da177e4
LT
812 IoAdapter->stop(IoAdapter);
813
814 return (0);
815}